Tomcat10连接模型

介绍下 Tomcat 10(10.1.x,NIO)连接管理模型 。内容从 整体架构 → 线程/连接角色 → 生命周期 → 状态转换 → 与 Spring Boot 内嵌模式的关系 → 常见瓶颈,形成一个"可用于排障和调优"的模型


一、整体架构总览(Tomcat 10 NIO)

Tomcat 10 默认使用 HTTP/1.1 NIO ConnectorHttp11NioProtocol),其连接管理是事件驱动 + 线程池执行模型:

复制代码
           ┌───────────┐
           │ Acceptor  │   接受 TCP 连接
           └─────┬─────┘
                 │
                 ▼
       ┌───────────────────┐
       │   Endpoint        │
       │  (NioEndpoint)    │
       └─────┬─────────────┘
             │
   ┌─────────▼─────────┐
   │      Poller       │   连接管理核心(Selector)
   │  (connection pool)│
   └─────────┬─────────┘
             │ 事件触发
             ▼
   ┌─────────────────────┐
   │   Executor /        │
   │   Worker Threads    │   执行业务
   └─────────────────────┘

核心思想
连接(Socket)与线程(Request 处理)分离

连接由 Poller 管,线程只在"真正处理请求"时使用。


二、核心组件与职责

1️⃣ Connector / Endpoint

  • 负责网络层

  • 参数:maxConnections, acceptCount, connectionTimeout

  • 在 Tomcat 10 中默认实现是:

    org.apache.tomcat.util.net.NioEndpoint

Endpoint 管三件事:

  • Acceptor(接连接)
  • Poller(管连接)
  • SocketWrapper / Buffer 池

2️⃣ Acceptor(接入层)

职责

  • 调用 ServerSocketChannel.accept()
  • 创建 SocketChannel
  • 注册到 Poller

关键参数

  • acceptCount:backlog 队列
  • 受 OS somaxconn 影响

特点

  • 不处理请求
  • 只负责把连接交给 Poller
  • 通常 1 个线程

3️⃣ Poller(连接管理核心)

职责(非常重要)

  • 维护 Selector

  • 管理所有活跃 Socket

  • 监听事件:

    • READ
    • WRITE
    • TIMEOUT
  • 管理 keep-alive

  • 管理 Socket 状态机

Poller = Tomcat 的"连接池"

  • 所有 Socket(包括 idle)都在这里
  • maxConnections 限制

CLOSE_WAIT / ESTABLISHED / IDLE 都属于 Poller 管理范围


4️⃣ Executor / Worker 线程池

职责

  • 处理 HTTP 请求
  • 调用 Filter / Servlet / Spring MVC
  • 不管理连接生命周期

关键参数

  • maxThreads
  • minSpareThreads

三、连接生命周期(一次完整 HTTP/1.1)

Step 1:建立 TCP 连接

复制代码
Client → SYN
Server → SYN+ACK
Client → ACK

→ Acceptor 接收

→ 注册到 Poller

→ 状态:ESTABLISHED (IDLE)


Step 2:接收请求数据

  • Poller 监听到 READ 事件
  • 创建 Http11Processor
  • 投递给 Executor

Step 3:业务处理

  • Worker 线程处理:

    • Filter
    • Servlet
    • Spring Controller
  • 构建 Response


Step 4:响应写回

  • Poller 负责 WRITE
  • Response 写回 socket

Step 5:连接去向

✔ keep-alive

复制代码
IDLE → Poller

✔ 非 keep-alive

复制代码
close() → TIME_WAIT

四、连接状态机(简化)

复制代码
NEW
 ↓
ESTABLISHED
 ↓
READING
 ↓
PROCESSING (worker)
 ↓
WRITING
 ↓
IDLE (keep-alive)
 ↓
CLOSED / TIME_WAIT

⚠️ 如果:

  • 客户端先 close
  • Tomcat 未 close

CLOSE_WAIT


五、Tomcat 10 的关键限制点

1️⃣ maxConnections(连接池上限)

  • 默认:8192

  • 包含:

    • idle keep-alive
    • 正在处理
    • CLOSE_WAIT(未 close)

超过后:

  • 新连接进入 acceptCount
  • 再超 → 拒绝连接

2️⃣ maxThreads(业务并发上限)

  • 你配置:800
  • 只限制"正在处理的请求"
  • 不限制连接数

3️⃣ acceptCount(缓冲区)

  • 你配置:1000
  • TCP 层 backlog

六、Spring Boot 内嵌 Tomcat 的映射关系

yaml 复制代码
server:
  tomcat:
    max-connections: 8192
    accept-count: 1000
    threads:
      max: 800
Spring Boot Tomcat
max-connections Endpoint.maxConnections
accept-count Acceptor backlog
threads.max Executor.maxThreads

七、Tomcat 10 的几个"反直觉点"(很重要)

❗ 1. 连接多 ≠ 线程多

  • 10k 连接
  • 800 线程
  • 完全正常

❗ 2. CLOSE_WAIT 会吃掉连接池

  • 不会自动释放
  • 是服务端 bug 信号

❗ 3. Poller 不等于线程池

  • Poller 是 I/O 事件循环
  • Executor 是业务执行

八、常见问题与调优方向

你遇到的:

CLOSE_WAIT ≈ 3700 → 服务不可用

在 Tomcat 10 模型下意味着:

  • Poller 的连接池被"半死连接"占满
  • Acceptor 无法接新连接
  • 表现为端口存在但无响应

九、一句话总结(工程视角)

Tomcat 10 采用"事件驱动连接管理 + 线程池业务处理"的模型,Poller 统一管理 Socket 生命周期,Executor 只在请求处理阶段介入;任何 CLOSE_WAIT 的累积都会直接耗尽连接池,导致服务雪崩。

相关推荐
步行cgn1 天前
MyBatis 动态 SQL 完全指南
sql·tomcat·mybatis
SemiTris2 天前
从Controller到Tomcat底层请求链路全解析
java·tomcat
程序员良辰3 天前
【TongWeb8】使用 Crontab 定时重启和检测 TongWeb 服务
java·中间件·tomcat
上海云盾商务经理杨杨3 天前
Tomcat 弱配置漏洞渗透实战!批量 getshell 高频漏洞
java·web安全·tomcat
小张同学a.7 天前
zabbix企业级监控平台3——服务监控与API实战
linux·运维·mysql·nginx·tomcat·zabbix
xxwl58513 天前
数据库后端接口测试报告
spring boot·mysql·tomcat
次次皮15 天前
Linux 下通过 XShell 手动更新 Tomcat 应用并重启
前端·tomcat·jar
Listen·Rain16 天前
用AI开发出一个AI
java·人工智能·spring boot·tomcat·intellij-idea·mybatis·visual studio
Full Stack Developme17 天前
SpringBoot 内嵌 Tomcat 的启动流程
spring boot·后端·tomcat
Full Stack Developme17 天前
Tomcat 如何处理HTTP请求
java·http·tomcat