Linux下Tomcat线程池优化实战
一 核心参数与推荐范围
- 线程池参数(Executor)
- maxThreads:最大工作线程数。CPU 密集型建议约为CPU 核心数的 1–2 倍;I/O 密集型建议约为2–4 倍。默认值:200。
- minSpareThreads:最小空闲线程数,保证有线程可立即处理请求。默认值:25。
- maxIdleTime:空闲线程最大存活时间,超过将被回收。默认值:60000 ms。
- maxQueueSize:请求等待队列长度(使用共享线程池时生效)。默认值:Integer.MAX_VALUE(过大,建议显式设置)。
- prestartminSpareThreads:启动时即预热创建最小空闲线程。
- 连接器参数(Connector)
- protocol:优先使用 HTTP/1.1 + NIO(如:org.apache.coyote.http11.Http11NioProtocol)。
- maxConnections:Tomcat 同时接受/处理的最大连接数。默认值:NIO/NIO2 为10000,APR 为8192。
- acceptCount:当所有工作线程忙时,TCP 等待队列长度(超出后连接可能被拒绝)。默认值:100。
- connectionTimeout:连接超时。示例:20000 ms。
- enableLookups:禁用 DNS 反查,减少阻塞。
- 可选:compression 开启传输压缩,降低带宽占用。
- 经验范围与取舍
- 常见将 maxThreads 设置在500–800起步,结合压测再上探;队列不宜无限大,避免长排队导致尾延迟升高。
- 若 acceptCount 经常打满,说明后端处理能力不足或线程数偏低,应优先提升处理能力而非一味增大队列。
- 使用共享 Executor 可让多个 Connector 复用同一线程池,便于统一治理与调优。
二 server.xml 配置示例
- 共享线程池 + NIO Connector(建议在生产使用)
<Executor name="tomcatThreadPool"
namePrefix="catalina-exec-"
maxThreads="700"
minSpareThreads="100"
maxSpareThreads="400"
maxQueueSize="300"
maxIdleTime="60000"
prestartminSpareThreads="true"/>
<Connector executor="tomcatThreadPool"
port="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443"
maxConnections="10000"
acceptCount="500"
enableLookups="false"
compression="on"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript"
URIEncoding="UTF-8"/>
- 要点
- 将 maxQueueSize 设置为有限值(如300),避免队列无限增长。
- 通过 executor 引用共享线程池,多个 Connector 可共用。
- 按需开启 compression 与设置 URIEncoding。
三 Linux 与 JVM 配套优化
- 文件描述符与内核网络
- 提升进程可打开文件数:在 systemd 服务中设置 LimitNOFILE=65535,或执行 ulimit -n 65535。
- 内核网络(示例值,按业务与内核版本调优):
- net.core.rmem_max / wmem_max:如 1310720
- net.ipv4.tcp_tw_reuse:1;net.ipv4.tcp_tw_recycle:0
- net.ipv4.tcp_fin_timeout:60;net.ipv4.tcp_syn_retries:1;net.ipv4.tcp_synack_retries:1
- net.ipv4.tcp_fastopen:3
- JVM 参数(置于 bin/catalina.sh 的 JAVA_OPTS)
- 堆与模式:如 -Xms2g -Xmx2g -server(建议 Xms 与 Xmx 一致,减少扩容抖动)。
- 线程栈:如 -Xss1m(过大限制可创建线程数,过小易栈溢出)。
- 元空间(JDK 8+):如 -XX:MetaspaceSize=… -XX:MaxMetaspaceSize=…。
- 垃圾回收:JDK 9+ 默认 G1GC;低版本可选 Parallel GC 或 CMS(视停顿与吞吐目标而定)。
四 监控与验证
- JMX 与可视化
- 启动 Tomcat 开启 JMX(在 catalina.sh 设置 JMX 相关环境变量),使用 JConsole/VisualVM 观察线程池指标:当前线程数、最大线程数、队列积压、处理时间 等。
- 日志与状态页
- 分析 catalina.out、localhost_access_log、localhost.*.log 识别错误码、慢请求与异常堆栈。
- 通过 /manager/status(需配置用户与权限)查看线程与连接器运行状态。
- 压测与阈值
- 使用 ab/wrk/jmeter 进行阶梯压测,观察 吞吐、P95/P99 延迟、错误率、队列积压 随 maxThreads/acceptCount/maxQueueSize 的变化,逐步收敛到最优配置。
五 调优步骤与注意事项
- 基线采集:记录当前 CPU、内存、I/O、网络、GC 停顿、线程与队列 基线。
- 设定目标:明确业务可接受的 P95/P99 延迟 与 错误率 上限。
- 逐步调参
- 先确定 maxThreads(CPU 密集 1–2×核数;I/O 密集 2–4×核数),再调节 acceptCount 与 maxQueueSize,避免队列过长。
- 结合 maxConnections 与系统承载能力,防止连接风暴。
- 关联组件
- 同步优化 数据库连接池(如 HikariCP/DBCP)与下游依赖,避免线程在外部资源上长时间阻塞。
- 静态资源交由 Nginx/CDN,减轻 Tomcat 负担。
- 变更与回滚
- 每次只变更一个关键参数,保持其他条件一致;压测通过后灰度上线,异常快速回滚。
- 安全与稳定
- 生产建议禁用 DNS 反查(enableLookups=false),并可关闭 8005 shutdown 端口 或改为复杂口令。