💡 第二章:Tomcat 核心架构拆解
目录
- [2.1 整体分层结构](#2.1 整体分层结构)
- [2.2 各组件职责详解](#2.2 各组件职责详解)
- [2.3 server.xml 配置示例](#2.3 server.xml 配置示例)
- [2.4 生命周期接口与启动流程](#2.4 生命周期接口与启动流程)
- [2.5 组件间通信机制](#2.5 组件间通信机制)
- [2.6 本章小结](#2.6 本章小结)
2.1 整体分层结构
架构层次图
Wrapper 层 Context 层 Host 层 Engine 层 Connector 层 Service 层 Server 层 Wrapper
Servlet包装器 Wrapper
Servlet包装器 Context
Web应用上下文 Context
Web应用上下文 Host
虚拟主机 Host
虚拟主机 Engine
请求处理引擎 Connector
协议适配层 Connector
协议适配层 Service
服务单元 Server
整体容器
层次关系说明
| 层次 | 组件 | 数量关系 | 职责 |
|---|---|---|---|
| Server | 1个 | 1:1 | 整个 Tomcat 实例的容器 |
| Service | 1个 | 1:1 | 服务单元,包含 Connector 和 Engine |
| Connector | 多个 | 1:N | 协议适配,处理不同协议请求 |
| Engine | 1个 | 1:1 | 请求处理引擎,路由请求到 Host |
| Host | 多个 | 1:N | 虚拟主机,根据域名路由 |
| Context | 多个 | 1:N | Web 应用上下文,对应一个应用 |
| Wrapper | 多个 | 1:N | Servlet 包装器,管理 Servlet 实例 |
2.2 各组件职责详解
2.2.1 Server 组件
职责
- 整体容器:Tomcat 实例的根容器
- 生命周期管理:启动、停止整个 Tomcat 实例
- 配置管理:加载和管理全局配置
核心功能
java
// Server 接口核心方法
public interface Server extends Lifecycle {
// 添加服务
void addService(Service service);
// 移除服务
void removeService(Service service);
// 查找服务
Service findService(String name);
// 获取所有服务
Service[] findServices();
}
配置示例
xml
<Server port="8005" shutdown="SHUTDOWN">
<!-- 全局监听器 -->
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- 全局资源 -->
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- 服务配置 -->
<Service name="Catalina">
<!-- Connector 和 Engine 配置 -->
</Service>
</Server>
2.2.2 Service 组件
职责
- 服务单元:将 Connector 和 Engine 组合在一起
- 请求路由:将 Connector 接收的请求路由到 Engine
- 生命周期协调:协调 Connector 和 Engine 的生命周期
核心功能
java
// Service 接口核心方法
public interface Service extends Lifecycle {
// 获取引擎
Engine getContainer();
// 设置引擎
void setContainer(Engine engine);
// 添加连接器
void addConnector(Connector connector);
// 移除连接器
void removeConnector(Connector connector);
// 查找连接器
Connector[] findConnectors();
}
2.2.3 Connector 组件
职责
- 协议适配:将不同协议的请求转换为标准格式
- I/O 处理:处理网络 I/O 操作
- 请求解析:解析 HTTP 请求头和参数
支持的协议
| 协议 | 实现类 | 说明 |
|---|---|---|
| HTTP/1.1 | Http11NioProtocol | 非阻塞 I/O |
| HTTP/1.1 | Http11AprProtocol | APR 原生实现 |
| HTTP/2 | Http2Protocol | HTTP/2 协议支持 |
| AJP | AjpNioProtocol | Apache JServ Protocol |
配置示例
xml
<!-- HTTP Connector -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200"
minSpareThreads="10"
maxSpareThreads="50"
acceptCount="100"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json" />
<!-- AJP Connector -->
<Connector port="8009" protocol="AJP/1.3"
redirectPort="8443"
maxThreads="200"
minSpareThreads="10"
maxSpareThreads="50" />
2.2.4 Engine 组件
职责
- 请求处理引擎:处理所有请求的入口点
- Host 路由:根据请求的 Host 头路由到相应的 Host
- 默认 Host:处理没有匹配 Host 的请求
核心功能
java
// Engine 接口核心方法
public interface Engine extends Container {
// 获取默认主机
String getDefaultHost();
// 设置默认主机
void setDefaultHost(String defaultHost);
// 获取主机
Host getHost(String name);
// 添加主机
void addChild(Container child);
}
配置示例
xml
<Engine name="Catalina" defaultHost="localhost">
<!-- 集群配置 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
<!-- 主机配置 -->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- Context 配置 -->
</Host>
<!-- 虚拟主机配置 -->
<Host name="api.example.com" appBase="webapps/api"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="api-app" />
</Host>
</Engine>
2.2.5 Host 组件
职责
- 虚拟主机:根据域名提供不同的 Web 服务
- Context 路由:根据请求路径路由到相应的 Context
- 应用管理:管理部署在主机上的 Web 应用
核心功能
java
// Host 接口核心方法
public interface Host extends Container {
// 获取应用基础目录
String getAppBase();
// 设置应用基础目录
void setAppBase(String appBase);
// 查找上下文
Context findContext(String name);
// 添加上下文
void addChild(Container child);
}
配置示例
xml
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<!-- 应用上下文 -->
<Context path="/myapp" docBase="myapp" reloadable="true">
<!-- 应用特定配置 -->
</Context>
<!-- 默认应用 -->
<Context path="" docBase="ROOT" />
<!-- 访问日志 -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
2.2.6 Context 组件
职责
- Web 应用上下文:代表一个 Web 应用
- Servlet 路由:根据 URL 路径路由到相应的 Servlet
- 资源管理:管理应用内的静态资源和类文件
核心功能
java
// Context 接口核心方法
public interface Context extends Container {
// 获取应用路径
String getPath();
// 设置应用路径
void setPath(String path);
// 获取文档基础目录
String getDocBase();
// 设置文档基础目录
void setDocBase(String docBase);
// 添加 Servlet 映射
void addServletMappingDecoded(String pattern, String name);
}
配置示例
xml
<Context path="/myapp" docBase="myapp" reloadable="true">
<!-- 环境变量 -->
<Environment name="app.config" value="production" type="java.lang.String" />
<!-- 资源引用 -->
<Resource name="jdbc/MyDB" auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb"
username="user"
password="pass"
maxTotal="20"
maxIdle="10"
maxWaitMillis="10000" />
<!-- Servlet 映射 -->
<Servlet name="MyServlet" class="com.example.MyServlet" />
<ServletMapping name="MyServlet" urlPattern="/myservlet" />
</Context>
2.2.7 Wrapper 组件
职责
- Servlet 包装器:管理单个 Servlet 实例
- 生命周期管理:管理 Servlet 的 init、service、destroy 方法
- 实例管理:管理 Servlet 实例的创建和销毁
核心功能
java
// Wrapper 接口核心方法
public interface Wrapper extends Container {
// 获取 Servlet 类名
String getServletClass();
// 设置 Servlet 类名
void setServletClass(String servletClass);
// 加载 Servlet
Servlet load() throws ServletException;
// 分配 Servlet 实例
Servlet allocate() throws ServletException;
}
2.3 server.xml 配置示例
完整配置示例
xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<!-- 全局监听器 -->
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- 全局资源 -->
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- 服务配置 -->
<Service name="Catalina">
<!-- HTTP 连接器 -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200"
minSpareThreads="10"
maxSpareThreads="50"
acceptCount="100"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json"
useSendfile="true" />
<!-- AJP 连接器 -->
<Connector port="8009" protocol="AJP/1.3"
redirectPort="8443"
maxThreads="200"
minSpareThreads="10"
maxSpareThreads="50" />
<!-- 引擎配置 -->
<Engine name="Catalina" defaultHost="localhost">
<!-- 集群配置 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
<!-- 主机配置 -->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<!-- 应用上下文 -->
<Context path="/myapp" docBase="myapp" reloadable="true">
<Resource name="jdbc/MyDB" auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb"
username="user"
password="pass"
maxTotal="20"
maxIdle="10"
maxWaitMillis="10000" />
</Context>
<!-- 访问日志 -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<!-- 虚拟主机 -->
<Host name="api.example.com" appBase="webapps/api"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="api-app" />
</Host>
</Engine>
</Service>
</Server>
配置层次关系
Server GlobalNamingResources Service: Catalina Connector: HTTP/1.1 Connector: AJP/1.3 Engine: Catalina Host: localhost Host: api.example.com Context: /myapp Valve: AccessLogValve Context: api-app
2.4 生命周期接口与启动流程
2.4.1 Lifecycle 接口
生命周期状态
java
public enum LifecycleState {
NEW(false, null),
INITIALIZING(false, "before_init"),
INITIALIZED(false, "after_init"),
STARTING_PREP(false, "before_start"),
STARTING(true, "configure_start"),
STARTED(true, "after_start"),
STOPPING_PREP(true, "before_stop"),
STOPPING(false, "configure_stop"),
STOPPED(false, "after_stop"),
FAILED(false, null),
DESTROYING(false, "before_destroy"),
DESTROYED(false, "after_destroy"),
MUST_STOP(true, null),
MUST_DESTROY(false, null);
}
核心方法
java
public interface Lifecycle {
// 添加生命周期监听器
void addLifecycleListener(LifecycleListener listener);
// 移除生命周期监听器
void removeLifecycleListener(LifecycleListener listener);
// 获取生命周期监听器
LifecycleListener[] findLifecycleListeners();
// 启动
void start() throws LifecycleException;
// 停止
void stop() throws LifecycleException;
// 获取状态
LifecycleState getState();
// 获取状态名称
String getStateName();
}
2.4.2 启动流程
启动序列图
Bootstrap Catalina StandardServer StandardService Connector StandardEngine StandardHost StandardContext main() load() init() init() init() init() init() start() start() start() start() start() start() Bootstrap Catalina StandardServer StandardService Connector StandardEngine StandardHost StandardContext
详细启动步骤
1. Bootstrap 启动
java
// Bootstrap.main() 方法
public static void main(String args[]) {
Bootstrap bootstrap = new Bootstrap();
bootstrap.init();
bootstrap.start();
}
2. Catalina 初始化
java
// Catalina.start() 方法
public void start() {
// 1. 创建服务器
if (getServer() == null) {
load();
}
// 2. 启动服务器
if (getServer() == null) {
log.fatal("Cannot start server. Server object is not configured.");
return;
}
long t1 = System.nanoTime();
// 3. 启动服务器
getServer().start();
long t2 = System.nanoTime();
if(log.isInfoEnabled()) {
log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
}
}
3. 组件初始化顺序
java
// 初始化顺序
1. Server.init()
2. Service.init()
3. Connector.init()
4. Engine.init()
5. Host.init()
6. Context.init()
7. Wrapper.init()
4. 组件启动顺序
java
// 启动顺序
1. Server.start()
2. Service.start()
3. Engine.start()
4. Host.start()
5. Context.start()
6. Wrapper.start()
7. Connector.start()
2.5 组件间通信机制
2.5.1 请求流转机制
请求处理流程图
HTTP请求 Connector CoyoteAdapter Engine Host Context Wrapper Servlet Response Connector HTTP响应
关键适配器
java
// CoyoteAdapter 适配器
public class CoyoteAdapter implements Adapter {
@Override
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
// 1. 创建 Request 和 Response 对象
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
// 2. 设置请求属性
request.setCoyoteRequest(req);
response.setCoyoteResponse(res);
// 3. 调用容器的 service 方法
connector.getService().getContainer().getPipeline()
.getFirst().invoke(request, response);
}
}
2.5.2 Pipeline 和 Valve 机制
Pipeline 接口
java
public interface Pipeline {
// 获取基础 Valve
Valve getBasic();
// 设置基础 Valve
void setBasic(Valve valve);
// 添加 Valve
void addValve(Valve valve);
// 移除 Valve
void removeValve(Valve valve);
// 获取第一个 Valve
Valve getFirst();
}
Valve 接口
java
public interface Valve {
// 获取下一个 Valve
Valve getNext();
// 设置下一个 Valve
void setNext(Valve valve);
// 处理请求
void invoke(Request request, Response response)
throws IOException, ServletException;
// 获取信息
String getInfo();
}
Valve 链示例
java
// 标准 Valve 链
StandardEngine -> StandardHost -> StandardContext -> StandardWrapper
// 每个容器都有对应的 Pipeline
Engine: EngineValve
Host: AccessLogValve -> ErrorReportValve -> StandardHostValve
Context: StandardContextValve
Wrapper: StandardWrapperValve
2.6 本章小结
关键要点
-
分层架构:
- Server → Service → Connector + Engine → Host → Context → Wrapper
- 每层都有明确的职责和接口定义
-
组件职责:
- Server:整体容器,管理全局配置
- Service:服务单元,协调 Connector 和 Engine
- Connector:协议适配,处理网络 I/O
- Engine:请求引擎,路由到 Host
- Host:虚拟主机,管理 Web 应用
- Context:应用上下文,管理 Servlet
- Wrapper:Servlet 包装器,管理 Servlet 实例
-
生命周期管理:
- 所有组件都实现 Lifecycle 接口
- 启动顺序:Server → Service → Engine → Host → Context → Wrapper → Connector
- 停止顺序:与启动顺序相反
-
通信机制:
- Pipeline 和 Valve 机制实现请求处理链
- CoyoteAdapter 负责协议适配
- 每个容器都有对应的 Valve 链
配置要点
-
server.xml 配置:
- 严格按照层次结构配置
- 注意组件的依赖关系
- 合理设置连接器参数
-
性能考虑:
- 连接器线程池配置
- 主机和应用管理
- 访问日志和监控
下一步学习
在下一章中,我们将深入探讨 Tomcat 的请求处理原理,了解从 HTTP 请求到 Servlet 响应的完整流程,以及各个组件在请求处理中的作用。
相关资源: