【关于Tomcat 并发量】

探讨 Tomcat 的并发量,不能简单地给出一个固定的数字,因为 Tomcat 的理论并发上限实际业务能支撑的并发量(QPS/TPS) 是两个完全不同的概念。

在当前的架构环境下(截至 2026 年,Tomcat 10.1/11 及 Java 21+ 已广泛普及),我们可以从核心配置、计算模型、最新技术(虚拟线程)以及全链路优化四个维度来彻底搞透 Tomcat 的并发量。


一、 决定 Tomcat 并发上限的核心参数

server.xml<Connector> 标签中,有三个核心参数决定了 Tomcat 的"物理"并发上限:

  1. maxThreads(最大工作线程数)
    • 含义 :Tomcat 能同时处理请求的最大线程数。默认值通常是 200
    • 作用 :决定了同时能处理多少个业务请求。如果请求数超过此值,多余的请求将进入等待队列。
    • 建议值 :根据 CPU 核数和业务类型调整。CPU 密集型建议 CPU核数 + 1;IO 密集型(如查数据库、调外部接口)建议 200 ~ 800
  2. maxConnections(最大连接数)
    • 含义 :Tomcat 同时能接受的最大 TCP 连接数。NIO 模式下默认 10000,APR 模式下默认 8192
    • 作用:决定了 Tomcat 能"挂起"多少个客户端连接。连接建立后,会被分配给工作线程处理;如果线程满了,连接会保持在已连接状态等待线程释放。
  3. acceptCount(等待队列长度)
    • 含义 :当 maxConnections 也满了时,操作系统层面等待 TCP 握手的队列长度。默认 100
    • 作用 :如果超过 maxConnections + acceptCount,Tomcat 将直接拒绝连接(客户端收到 Connection Refused)。

💡 避坑指南 :很多新手以为把 maxThreads 调到 2000 并发就能翻倍,这是错误的。线程过多会导致 CPU 频繁上下文切换,反而让系统崩溃。


二、 实际并发量(QPS)的计算公式

在实际业务中,Tomcat 的并发处理能力遵循利特尔法则(Little's Law)

最大 QPS = maxThreads / 平均响应时间(秒)

举个例子:

  • 假设 maxThreads = 200
  • 场景 A(纯内存计算,极快) :平均响应时间 10ms (0.01s)
    • 理论 QPS = 200 / 0.01 = 20,000 QPS
  • 场景 B(涉及复杂 SQL 和外部 RPC,较慢) :平均响应时间 200ms (0.2s)
    • 理论 QPS = 200 / 0.2 = 1,000 QPS

结论 :Tomcat 的并发瓶颈往往不在 Tomcat 本身 ,而在于后端应用的处理速度(尤其是数据库和第三方接口的 IO 耗时)


三、 🚀 2026年最新突破:虚拟线程(Virtual Threads)

如果你使用的是 Tomcat 10.1+ 或 Tomcat 11 并且运行在 Java 21+ 环境下,Tomcat 的并发模型发生了革命性的变化。

传统的 NIO 模型受限于 OS 物理线程数(通常几百到一千),而虚拟线程 让 Tomcat 可以轻松应对数万级别的并发阻塞 IO

开启虚拟线程的配置(server.xml):

xml 复制代码
<!-- 定义虚拟线程执行器 -->
<Executor name="tomcatThreadPoolVirtual" 
          type="org.apache.catalina.core.StandardVirtualThreadExecutor"/>

<!-- 在 Connector 中使用 -->
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           executor="tomcatThreadPoolVirtual"
           maxConnections="20000" 
           acceptCount="500" />
  • 优势 :在虚拟线程模式下,maxThreads 的限制被打破。当请求遇到数据库 IO 阻塞时,虚拟线程会自动让出底层载体线程(Carrier Thread),Tomcat 可以轻松维持数万个并发连接而不耗尽内存或导致 CPU 上下文切换风暴。

四、 如何提升 Tomcat 的实际并发量?(全链路优化)

要提升系统的真实并发量,单改 Tomcat 配置是没用的,必须进行"木桶效应"的全链路优化:

1. 操作系统层面 (OS)
  • 文件描述符限制 :执行 ulimit -n,确保其值大于 Tomcat 的 maxConnections(建议设置为 65535 或更高)。
  • TCP 队列优化 :修改 /etc/sysctl.conf
    • net.core.somaxconn = 2048 (必须大于 Tomcat 的 acceptCount
    • net.ipv4.tcp_max_syn_backlog = 2048
    • net.ipv4.tcp_tw_reuse = 1 (允许复用 TIME-WAIT sockets)
2. 应用与数据库层面(最核心的瓶颈)
  • 数据库连接池 :Tomcat 有 500 个线程,但 HikariCP/Druid 只有 50 个数据库连接,那么实际并发上限就是 50 。必须合理配置数据库连接池大小(通常 CPU核数 * 2 + 磁盘数 是个不错的经验值)。
  • 异步化改造 :对于非核心链路(如发短信、写日志、发 MQ),使用 @Async 或消息队列异步处理,快速释放 Tomcat 线程。
  • 引入缓存:使用 Redis 拦截大量读请求,避免请求穿透到数据库耗尽 Tomcat 线程。
3. JVM 层面
  • 并发量上来后,GC 压力会剧增。建议升级至 G1 GCZGC(Java 21 中 ZGC 已默认分代,停顿时间可控制在 1ms 以内),避免因 GC Stop-The-World 导致 Tomcat 线程堆积超时。

五、 如何测试你的 Tomcat 并发量?

不要靠猜,使用压测工具在测试环境摸底:

  1. JMeter:最常用,适合模拟复杂的业务链路和混合场景。
  2. wrk / wrk2:基于 C 语言的轻量级压测工具,适合测试纯 API 的极限 QPS 和延迟分布。
  3. Apache Bench (ab):最简单,适合单机快速验证。

压测观察指标

  • TPS/QPS:是否达到预期。
  • RT (响应时间):随着并发增加,RT 是否出现断崖式上升。
  • Tomcat 线程池状态 :通过 JMX 或 Spring Boot Actuator (/actuator/metrics/tomcat.threads.busy) 观察线程是否被打满。
  • 错误率 :是否出现 Connection refusedTimeout

总结

  • 理论上限 :由 maxConnectionsacceptCount 决定(通常上万)。
  • 处理上限 :由 maxThreads 决定(通常 200~800)。
  • 实际业务并发 :由 maxThreads / 接口平均响应时间 决定。
  • 未来趋势 :拥抱 Java 21 + Tomcat 10.1/11 的虚拟线程,彻底解决传统线程池模型下的 IO 阻塞瓶颈。