Tomcat
1.1 简单讲讲tomcat结构,以及其类加载器流程,线程模型等。
Apache Tomcat是一个开源的Servlet和JavaServer Pages(JSP)容器,用于部署和运行Java Web应用程序。其主要结构和组件包括:
- Tomcat结构:
- Catalina:Catalina是Tomcat的核心引擎,负责处理请求与响应,并管理整个生命周期中的Web应用。
- Connector:连接器是Tomcat服务器与客户端之间的通信接口,它监听特定端口上的HTTP请求,并将请求传递给Catalina进行处理。常见的连接器有BIO、NIO和APR等。
- Container:容器层级结构包括Engine、Host、Context和Wrapper,它们共同构成了一个层次化的管理结构,分别对应服务级别、虚拟主机级别、Web应用级别以及Servlet级别。
-
Engine
:顶级容器,代表整个Catalina Servlet引擎。 -
Host
:每个Engine下可以包含多个Host,代表服务器上的一个虚拟主机或IP地址+端口组合。 -
Context
:每个Host下可以有多个Context,代表一个Web应用程序上下文,即通常所说的部署在服务器上的WAR文件。 -
Wrapper
:最底层容器,代表了在Web应用程序中被加载的一个Servlet。
- 类加载器流程:
- Tomcat遵循Java标准的类加载器架构,并在此基础上进行了扩展以支持Web应用的隔离性。
- 类加载器主要有以下几类:
- Bootstrap ClassLoader:由JVM提供,加载核心Java库。
- System ClassLoader 或 Common ClassLoader:加载Tomcat自身的库和配置文件。
- Catalina ClassLoader:加载Tomcat服务器内部使用的类。
- Shared ClassLoader:共享类加载器,用于加载所有Web应用都可以访问的通用类库。
- WebApp ClassLoader(也称为Application ClassLoader):为每个Web应用创建独立的类加载器实例,加载各自WAR包中的类,从而实现不同Web应用间类的隔离。
- 线程模型:
- Tomcat使用多线程来并发处理客户端请求。
- 对于处理请求的线程池,Tomcat可以根据不同的连接器配置不同的线程模型,如:
- BIO(Blocking I/O):每个请求分配一个新的线程,适用于并发请求较少的情况。
- NIO(Non-blocking I/O):通过Selector复用少量线程处理大量连接,适合高并发场景。
- APR (Apache Portable Runtime):使用操作系统级别的API优化网络I/O性能,同样支持异步非阻塞模式。
1.2 tomcat如何调优,涉及哪些参数 。
Apache Tomcat调优是一个涉及多个方面的过程,主要是为了提高服务器性能、减少响应时间以及优化资源使用。以下是一些关键的Tomcat调优参数和策略:
- 内存配置(JVM参数):
-
-Xms
:设置JVM初始堆内存大小。 -
-Xmx
:设置JVM最大堆内存大小。 -
-XX:MaxMetaspaceSize
(Java 8及更高版本):设置元空间的最大大小,用于存储类元数据等。 -
-Xmn
或-XX:NewRatio
:调整年轻代与老年代的大小比例。
- 垃圾回收器选择与参数调整:
-
-XX:+UseG1GC
或-XX:+UseConcMarkSweepGC
等:选择适合应用特性的垃圾收集器。 -
-XX:MaxTenuringThreshold
:控制对象晋升到老年代的年龄阈值。
- 连接器优化:
-
maxThreads
:在server.xml
中配置Connector组件,设置最大并发处理线程数。 -
acceptCount
:当所有请求处理线程都忙碌时,可以排队等待的最大请求数量。 -
connectionTimeout
:设置客户端连接超时时间。 -
enableLookups
:禁用DNS查找以加快处理速度(通常设为false
)。 - 启用压缩 (
compression
和compressableMimeType
):对特定类型的HTTP响应进行压缩,降低网络传输负载。
- 静态资源缓存:
- 在
server.xml
中的Context
元素中配置resources
标签,并启用静态资源缓存。
- Tomcat内部机制优化:
- 考虑是否使用
apr
连接器来提升I/O性能。 - 根据实际情况设置线程池相关参数,如
minSpareThreads
、maxSpareThreads
等。
- 类加载器优化:
- 控制Web应用程序之间类库共享,合理配置
commonLoader
、sharedLoader
和webappLoader
。
- 日志输出级别:
- 适当调整日志级别,避免过多的日志输出消耗系统资源。
- SSL/TLS配置优化:
- 使用更高效的加密算法,减少握手阶段的延迟。
- 配置会话复用,提高HTTPS连接性能。
- 性能监控与分析工具:
- 利用JMX监控Tomcat性能指标。
- 使用JConsole、VisualVM或专门的APM工具(如New Relic、Dynatrace)监控和分析应用性能。
3.Netty
3.1 netty的线程模型,netty如何基于reactor模型上实现的。
Netty 是一个高性能的异步事件驱动网络应用框架,其线程模型基于Reactor模式实现。Reactor模式是一种处理大量并发I/O请求的设计模式,通过一个或多个反应器(Reactor)来监听和分发事件给相应的处理器进行处理。
在Netty中,Reactor线程模型主要有以下几种形式:
- 单线程Reactor模型:
- 仅使用一个NIO线程作为Selector,负责监听所有Channel上的事件。
- 当Channel上有新的连接请求、读写事件时,该线程会负责接收并调度到对应的Handler进行处理。
- 这种模型适用于CPU密集型任务且并发量不高的场景,因为所有事件处理都在同一个线程内完成。
- 多线程Reactor模型(主从Reactor或多线程EventLoopGroup):
- 使用一个Acceptor线程池(通常只有一个线程)监听新的客户端连接请求。
- 当有新的连接到来时,由Acceptor将新建立的SocketChannel注册到另一个I/O线程池中的某个工作线程上,这个线程(即EventLoop)负责后续的读写事件处理。
- 每个EventLoop有自己的Selector,并与一组Channel关联,负责这些Channel的所有I/O事件。
- 这种模型可以充分利用多核CPU资源,提高系统的并行处理能力。
- 主从Reactor多线程模型:
- 主Reactor用于接受新的连接请求,然后将其分配给从Reactor(也就是I/O线程池)。
- 从Reactor负责各自关联的Channel的I/O事件处理,每个从Reactor线程拥有自己的Selector,并在其上进行轮询和事件处理。
- 在高并发场景下,主从Reactor模型能够有效避免单一Reactor成为性能瓶颈。
3.2 为什么选择netty。
- 高性能与高并发: Netty基于NIO技术,采用了事件驱动和异步编程模型,能有效地利用系统资源,支持高并发连接。通过内存池化、零拷贝技术等优化手段,极大地提高了吞吐量和降低了延迟。
- 线程模型优化: Netty提供了灵活且高效的线程模型,如Reactor模式,可以避免频繁的线程上下文切换带来的开销,保证了系统的可伸缩性和稳定性。
- 易于使用和扩展: Netty提供了丰富的API和高度可定制化的组件,开发者可以方便地搭建和扩展网络应用,如Web服务器、游戏服务器、RPC框架等。同时,Netty对各种协议(如HTTP、FTP、WebSocket等)都有很好的支持。
- 健壮性与稳定性: Netty在网络异常处理、流量控制、超时重传等方面做了精心设计,保证了网络通信的健壮性和稳定性。同时,经过大量生产环境的检验,Netty在长期运行下的表现也非常稳定可靠。
- 社区活跃与持续更新: Netty背后有一个活跃的开源社区,不断对其功能进行改进和完善,及时修复bug,同时紧跟行业发展趋势,支持新的协议和特性,保障了其与时俱进的能力。
3.3 什么是TCP粘包,拆包。解决方式是什么。
TCP是一种面向连接、可靠的基于字节流的传输层协议。但在实际应用中,TCP为了提高传输效率,并不保证每个发送的数据包都能够单独作为一个完整的单位送达接收方,这就可能出现“TCP粘包”和“TCP拆包”现象。
- TCP粘包(Packet Coalescing): 当发送端连续发送多个小的数据包时,TCP有可能会合并这些数据包成为一个较大的数据块进行传输,接收端一次性接收多个数据包的内容,无法区分原本的单个数据包边界。这是因为TCP是以字节流的方式传输数据,而不保证应用层的消息边界。
- TCP拆包(Packet Fragmentation): 另一方面,如果一个大数据包在网络传输过程中因MTU(Maximum Transmission Unit)限制或其他网络因素被分割成了多个较小的数据包,接收端可能会分多次接收到这些数据包,造成原始数据的拆分,这也称为拆包现象。
解决TCP粘包和拆包问题的方式主要有以下几种:应用层固定长度大小区分、每个数据包末尾特定结束符
- 协议头设计: 设计自定义的应用层协议,加入明确的数据包长度字段,使得接收端可以根据长度字段正确区分不同的数据包。
- 消息边界标识: 在每个数据包末尾添加特定的结束符(delimiter),如换行符、特殊字符序列等,接收端通过检测这些结束符来识别一个完整消息的结束。
- 固定长度消息: 如果应用层消息长度都是固定的,可以直接根据长度来判断每个消息的结束位置。
- 消息帧设计: 设计成帧(framing)协议,例如在每个消息前加上消息头,消息头包含消息长度或序列号等信息,这样接收端可以根据消息头来解析出每个独立的消息。
- 基于协议内容的拆包粘包处理: 在接收端程序中实现逻辑,根据预先约定的协议解析数据,当接收到一定数量的数据后,按照协议格式解析出完整的消息。
3.4 netty的通讯协议是什么样的。
netty 并不是一个具体的通讯协议,而是一个用于简化高性能网络编程的 Java 开源框架。它提供了一系列工具和API,使得开发者能够更容易地实现基于各种传输协议的应用程序,比如TCP、UDP、HTTP等等。Netty 支持自定义协议的设计和实现,同时也提供了对多种标准协议的支持。
在Netty中,开发者可以根据自己的业务需求设计和实现自定义的通讯协议。通常情况下,一个自定义的通讯协议会在Netty中表现为一系列的编码(Encoder)和解码(Decoder)器,用于处理网络传输的数据流,确保数据在发送端按照协议进行编码封装,并在接收端正确解码还原。