1. Tomcat系统架构 - 连接器的设计
- Tomcat 连接器模块通过 ProtocolHandler(EndPoint + Processor)→ Adapter → Container 的链式设计,将网络 I/O、协议解析、Servlet 调用彻底解耦。
- 这种架构能够灵活支持多种 I/O(NIO/NIO2/APR)与协议(HTTP/AJP/HTTP2)组合,同时让业务逻辑(Servlet)专注于处理请求,不受底层变化影响。
1.1. Tomcat 总体架构概览
Tomcat 核心功能:
- 处理底层 Socket 连接,将网络字节流与请求/响应对象互转。
- 加载并管理 Servlet,完成具体的业务请求处理。
模块划分:
- 连接器(Connector):对外负责网络通信与协议解析。
- 容器(Container):对内负责 Servlet 生命周期管理与请求分发。
高内聚、低耦合原则:
- 将“经常变化”的部分与“相对稳定”的部分拆分,用接口与抽象基类封装不变部分,让子类实现变化点。
Tomcat架构:
Server
- 整个 Tomcat 实例的最顶层组件。
- 可以包含多个
Service
,以支持多端口或多协议并存。
Service
- “连接器 + 容器”的组合,仅负责将它们装配在一起(本身不充当逻辑处理)。
- 允许在同一个 Tomcat 实例中通过不同端口启动多个服务:
-
- 每个 Service 下可配多个 Connector,但只能配一个 Container。
Connector(连接器)
- 对外监听端口、接收客户端请求、解析协议、生成 Tomcat 内部 Request/Response。
- 将解析结果交给 Container,最终将 ServletResponse 序列化、写回客户端。
Container(容器)
- 负责加载、实例化、调用 Servlet;管理 ServletContext、Filter、Listener 等。
- 接收来自 Connector 的标准
ServletRequest
,调用相应 Servlet 输出结果。
1.2. 连接器的职责
连接器的职责(对容器屏蔽协议和 I/O 模型差异):
- 监听网络端口
- 接受客户端 TCP 连接
- 读取网络字节流
- 按照应用层协议(HTTP/AJP 等)解析字节流 → 生成 Tomcat 内部 Request/Response 对象
- 将 Tomcat Request 转换为
ServletRequest
,调用容器的service()
→ 得到ServletResponse
- 将
ServletResponse
转回 Tomcat Response,对应应用层协议序列化为字节流 - 将响应字节流写回客户端
核心设计原则:
- 高内聚
-
- 把“网络通信”“协议解析”“Request/Response 转换”三类职责分别集中到独立模块。
- 低耦合
-
- 各模块通过抽象接口交互,上层处理逻辑对下层具体实现(I/O、协议)不可见。
- 任何新增 I/O 模型或协议时,只需实现相应子类,整体框架不变。
1.3. 连接器的核心组件
连接器内部主要分为 ProtocolHandler(协议与 I/O 抽象)与 Adapter(请求转换与容器调用)两大部分,而 ProtocolHandler 又由 EndPoint 和 Processor 组成。
- ProtocolHandler
- 职责:
-
- 封装“网络 I/O 模型”与“应用层协议”的变化点。
- 提供统一接口,使 Container 只关注标准
ServletRequest
/ServletResponse
。
- 接口与抽象层次:
-
ProtocolHandler
(接口)
-
-
- 定义:启动、关闭、获取配置信息、传输 Request/Response 等方法。
-
-
AbstractProtocol
(抽象基类,实现 ProtocolHandler)
-
-
- 封装通用逻辑:线程池管理、生命周期管理、公共配置项等。
-
-
- 协议抽象基类
-
-
AbstractHttp11Protocol
(HTTP/1.1 相关共性逻辑)AbstractAjpProtocol
(AJP 相关共性逻辑)
-
-
- 具体实现类
-
-
Http11NioProtocol
、Http11Nio2Protocol
、Http11AprProtocol
等(组合不同 I/O 与 HTTP 协议)。AjpNioProtocol
、AjpNio2Protocol
、AjpAprProtocol
等(组合不同 I/O 与 AJP 协议)。
-
ProtocolHandler的两个重要部件
- EndPoint(通信端点):
- 定位:对传输层(TCP/IP 套接字)进行封装,负责底层网络监听与字节收发。
- 抽象接口:
-
EndPoint
(接口)AbstractEndpoint
(抽象实现)
- 关键子类:
-
NioEndpoint
:基于 Java NIO(Selector/非阻塞 I/O)实现。Nio2Endpoint
:基于 Java NIO2(AsynchronousChannel/异步 I/O)实现。AprEndpoint
:基于 APR(Apache Portable Runtime,本地 C/C++ 实现)实现。
- 内部组件:
-
- Acceptor
-
-
- 负责监听 ServerSocket,接受客户端连接。
- 每当有新连接,创建
SocketWrapper
并交给线程池执行。
-
-
- SocketProcessor
-
-
- 实现
Runnable
,封装具体的 Socket 处理逻辑。 - 运行时调用
Processor
(应用层协议解析模块)进行后续解析。
- 实现
-
-
- Executor(执行器)
-
-
- Java 线程池,用于并发执行
SocketProcessor
。 - 支持自定义或与 Tomcat 自带的
Executor
(可动态配置线程数、队列大小等)配合。
- Java 线程池,用于并发执行
-
- Processor(协议解析器):
- 定位:对应用层协议(HTTP/AJP 等)进行解析,将字节流→Tomcat
Request/Response 对象。 - 抽象接口:
-
Processor
(接口,定义解析请求、生成 Response、回写等方法)。AbstractProcessor
(抽象基类,封装共性属性与工具方法)。
- 具体实现:
-
Http11Processor
:实现 HTTP/1.1 解析(请求行、请求头、请求体)和响应拼装逻辑。AJPProcessor
:实现 AJP 协议解析与响应封装。- Octet-based 解析流程:
-
-
- 读取 Socket 字节流 → 解析请求行与请求头 → 提取请求参数、Cookie、URL 等。
- 填充 Tomcat 内部
Request
对象(包括请求方法、URI、协议版本、Header、InputStream)。 - 调用 Adapter,将 Tomcat
Request
转成ServletRequest
并交给容器处理。 - 从容器获得
ServletResponse
→ 填充 Tomcat 内部Response
→ 序列化成字节流 → 交还给 EndPoint 写回客户端。
-
- Adapter(适配器)
- 定位:将 Tomcat 内部的
Request
/Response
与标准 Servlet API 对象互转,并调用容器。 - 典型实现:
-
CoyoteAdapter
:Tomcat 连接器调用的默认适配器。
- 主要职责:
-
- 接收 Tomcat
Request
(Processor 解析后生成的内部类型)。 - 封装成
HttpServletRequest
/HttpServletResponse
(或通用ServletRequest
/ServletResponse
)。
- 接收 Tomcat
-
-
- 例如,将请求头、参数、InputStream 封装到
RequestFacade
;将输出流与状态码绑定到ResponseFacade
。
- 例如,将请求头、参数、InputStream 封装到
-
-
- 调用容器的
service()
方法,触发 Servlet/Filter 链的执行。 - 将容器产生的输出(
ServletOutputStream
、PrintWriter
等)回填到 TomcatResponse
对象。 - 控制容器异常处理与错误页面映射,比如捕获 Servlet 抛出的
ServletException
、IOError
等,映射为相应状态码。
- 调用容器的
1.4. 支持的 I/O 模型与协议组合
- I/O 模型:
-
- NIO(基于
java.nio
,Selector + 非阻塞 I/O)。 - NIO2(基于
java.nio.channels.AsynchronousChannel
,异步 I/O)。 - APR(基于 APR 本地库,C/C++ 实现,高性能)。
- NIO(基于
- 应用层协议:
-
- HTTP/1.1(最常用),
- AJP(与 Web 服务器(Apache、IIS)集成时使用),
- HTTP/2(多路复用、头压缩、二进制帧等特性)。
- 组合方式:
-
- 例如:
Http11NioProtocol
、Http11Nio2Protocol
、Http11AprProtocol
、AjpNio2Protocol
等。 - 每种组合对应一个具体的
ProtocolHandler
实现,内部复用相同的 EndPoint 和 Processor(针对协议的子类)。
- 例如: