Tomcat调优Service

本文皆为tomcat配置文件server.xm中Service模块配置优化

1. HTTP/1.1 协议的协议处理器选择

tomcat启动的时候,可以通过日志看到Connector使用的是哪一种协议处理器

1.1. Http11AprProtocol(推荐)

xml 复制代码
<Connector protocol="org.apache.coyote.http11.Http11AprProtocol" />
  • 基于 Apache Portable Runtime(APR)库实现的协议处理器;
  • 使用基于 epoll 或 kqueue 的 I/O 模型,支持非阻塞 I/O 和事件驱动模型,具有很好的性能和可伸缩性;
  • APR 是一种跨平台的 C 库,在性能和资源利用率方面比 Java 实现更优秀;
  • 适用于高并发、高吞吐量 Web 应用场景,特别是对于低延时、高并发的短连接请求具有更好的性能表现。

虽然apr在性能、资源利用等各方面综合能力都比nio2好,但需要注意的是:如果是docker模式使用tomcat则可直接使用apr模式,无需安装arp库;如果非docker环境,则需先安装APR库,并配置好相关的环境变量和库文件路径,比较麻烦。此外,APR 也有一些局限性,如不支持 Windows 系统、需要手动编译等。

1.2. Http11Nio2Protocol(小服务器适用)

xml 复制代码
<Connector protocol="org.apache.coyote.http11.Http11Nio2Protocol" />
  • 基于 NIO2(Java 7 版本引入)实现的高性能、可伸缩的协议处理器;
  • 支持非阻塞 I/O 和事件驱动模型,可以处理大量并发连接;
  • 安全性和稳定性较高,因为它是纯 Java 实现,不依赖任何外部库或操作系统;
  • 适用于高并发、高吞吐量的 Web 应用场景,特别是对于长连接、异步请求等复杂场景的性能表现更好。

相比之下,Http11Nio2Protocol更加易用和便捷(主要是不需要安装依赖库),但它相对于Http11AprProtocol性能、资源利用等略有劣势。

2.开启线程池

默认tomcat不开启线程池,即n个请求就是n个线程。而线程池是一种用于管理和复用线程的机制,它可以有效地管理线程的创建、执行和销毁,提供了一种线程资源的调度和管理方式。线程池在多线程编程中具有以下几个重要的作用:

  • 提高性能和效率:线程池可以避免频繁地创建和销毁线程,从而减少了线程创建和上下文切换的开销,提高了系统的性能和效率。通过重复利用已创建的线程,线程池可以更好地利用可用的系统资源。
  • 控制并发线程数量:线程池可以限制同时执行的线程数量,通过设置线程池的大小和可用的线程数,可以控制并发线程的数量,防止系统被过多的线程占用,避免资源耗尽和系统崩溃等问题。
  • 提供任务队列和调度机制:线程池通常会包含一个任务队列,用于存储等待执行的任务。当线程池中有空闲线程时,它会从任务队列中获取任务并执行。如果任务队列已满,新提交的任务可能会被暂时存储或根据配置进行拒绝处理。线程池可以根据自定义的调度策略来管理任务的执行顺序和优先级。
  • 提供线程管理和监控功能:线程池可以提供对线程的生命周期进行管理,包括线程的创建、销毁和状态管理。通过线程池,可以方便地监控线程的执行情况、统计线程的使用情况和性能指标,便于系统调优和故障排查。

总之,线程池在多线程编程中起着重要的作用,可以提高系统的性能、提供并发控制和任务调度机制,并简化线程管理和监控的工作。合理使用线程池可以避免线程过多造成的资源浪费和性能下降,同时提高代码的可维护性和可扩展性。

1.1配置开启

Service模块开启线程池

xml 复制代码
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="500" minSpareThreads="30"/>

Service模块链接器指定调用线程池

xml 复制代码
 <Connector executor="tomcatThreadPool"
    		port="8080" protocol..../>

最终配置如下图

1.2. 参数配置

当connector配置的参数与executor参数重复时,将以connector为主

参数 说明
protocol 协议处理器,极致性能、资源利用请使用apr
maxThreads Tomcat使用线程来处理接收的每个请求,这个值表示Tomcat可创建的最大的线程数,即支持的最大并发连接数,默认值是200,一般建议在 500 ~ 800
maxQueueSize 最大等待队列数,maxThreads满时,请求会进入等待队列
acceptCount 控制连接器可以接收的最大请求数量。当所有线程都处于繁忙状态且请求队列已满时,新的请求将被拒绝或丢弃。这个属性用于限制连接器队列中等待处理的请求数量,避免过多的请求导致服务器资源耗尽,即maxQueueSize满时,会触发此参数,此参数满就会拒绝后续的请求
enableLookups 使用DNS查询,用于控制是否启用 DNS 查找。如果启用了 enableLookups,Tomcat 将会尝试将客户端的 IP 地址解析为主机名,这可能会导致一些性能问题。如果禁用了 enableLookups,则 Tomcat 不会进行 DNS 查找,从而可以避免这些性能问题
minSpareThreads 最小空闲线程数,Tomcat 启动时的初始化的线程数,表示即使没有人使用也开这么多空线程等待,默认值是 10。
prestartminSpareThreads 在 Tomcat 初始化的时候就初始化 minSpareThreads 的参数值,如果不等于 true,minSpareThreads 的值就没啥效果了
maxIdleTime 如果当前线程大于初始化线程,那空闲线程存活的时间,单位毫秒,默认60000=60秒=1分钟
maxPostSize 设置由容器解析的URL参数的最大长度,小于0为禁用这个属性,默认为2097152(2M) 请注意, FailedRequestFilter 过滤器可以用来拒绝达到了极限值的请求
maxHttpHeaderSize http请求头信息的最大程度,超过此长度的部分不予处理。一般8K
compression 是否启用GZIP压缩 on为启用(文本数据压缩) off为不启用, force 压缩所有数据
compressableMimeType 压缩的数据类型
acceptorThreadCount protocol为nio或nio2才生效,用于指定接受连接的线程数量,默认1,但是一般设置2
disableUploadTimeout 上传时是否使用超时机制

1.2.1. maxThreads、acceptCount、maxQueueSize触发的顺序

在 Tomcat 中,请求的处理顺序如下:

  1. 当有新的请求到达时,Tomcat 首先检查连接器线程池中是否有可用的空闲线程。
  2. 如果有可用的空闲线程,Tomcat 会立即将请求分配给其中一个线程进行处理。
  3. 如果所有的线程都处于繁忙状态,Tomcat 将把请求放入连接器的请求队列中等待处理。
  4. 当请求进入请求队列时,Tomcat 会根据 maxQueueSize 参数来判断队列是否已满。
  5. 如果队列未满,请求将被添加到队列的末尾,等待线程池中的线程变为可用时再进行处理。
  6. 如果队列已满,Tomcat 将根据 acceptCount 参数来决定是否接受该请求。
  7. 如果请求被接受,Tomcat 将继续等待线程池中的线程变为可用后进行处理。
  8. 如果请求被拒绝或丢弃,客户端可能会收到连接失败或超时的错误。

因此,maxThreads 控制线程池中线程的数量,maxQueueSize 控制请求队列的容量,而 acceptCount 用于限制连接器可以接受的请求数量。在处理请求时,Tomcat 首先会尽量使用线程池中的空闲线程,然后将请求放入请求队列中,最后根据 acceptCount 来决定是否接受请求。

相关推荐
J不A秃V头A31 分钟前
iTextPDF中,要实现表格中的内容在数据长度超过边框时自动换行
java·pdf
椰椰椰耶1 小时前
【Spring】@RequestMapping、@RestController和Postman
java·后端·spring·mvc
CocoaAndYy1 小时前
Java实现限流算法(四种)
java·开发语言·算法
所待.3831 小时前
设计循环队列
java·开发语言·数据结构
脑瓜疼啊脑瓜疼1 小时前
Java中的自定义异常
java·开发语言
木子02042 小时前
SpringBoot线程问题
java·开发语言
TANGLONG2222 小时前
【C语言】字符和字符串函数(2)
java·c语言·c++·python·考研·面试·蓝桥杯
2401_854391082 小时前
新闻推荐系统:Spring Boot与大数据
java·spring boot·后端
编程、小哥哥3 小时前
手写mybatis之Mapper XML的解析和注册使用
xml·java·mybatis
哈哈皮皮虾的皮3 小时前
源码中为什么大多都使用for去作为死循环,而不是用while呢?
java