第二章-Tomcat核心架构拆解

💡 第二章: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 &quot;%r&quot; %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 &quot;%r&quot; %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 本章小结

关键要点

  1. 分层架构

    • Server → Service → Connector + Engine → Host → Context → Wrapper
    • 每层都有明确的职责和接口定义
  2. 组件职责

    • Server:整体容器,管理全局配置
    • Service:服务单元,协调 Connector 和 Engine
    • Connector:协议适配,处理网络 I/O
    • Engine:请求引擎,路由到 Host
    • Host:虚拟主机,管理 Web 应用
    • Context:应用上下文,管理 Servlet
    • Wrapper:Servlet 包装器,管理 Servlet 实例
  3. 生命周期管理

    • 所有组件都实现 Lifecycle 接口
    • 启动顺序:Server → Service → Engine → Host → Context → Wrapper → Connector
    • 停止顺序:与启动顺序相反
  4. 通信机制

    • Pipeline 和 Valve 机制实现请求处理链
    • CoyoteAdapter 负责协议适配
    • 每个容器都有对应的 Valve 链

配置要点

  1. server.xml 配置

    • 严格按照层次结构配置
    • 注意组件的依赖关系
    • 合理设置连接器参数
  2. 性能考虑

    • 连接器线程池配置
    • 主机和应用管理
    • 访问日志和监控

下一步学习

在下一章中,我们将深入探讨 Tomcat 的请求处理原理,了解从 HTTP 请求到 Servlet 响应的完整流程,以及各个组件在请求处理中的作用。


相关资源

相关推荐
lpfasd1233 小时前
第十章-Tomcat性能测试与实战案例
1024程序员节
IT古董3 小时前
【第五章:计算机视觉-项目实战之推荐/广告系统】2.粗排算法-(4)粗排算法模型多目标算法(Multi Task Learning)及目标融合
人工智能·算法·1024程序员节
RainSky_3 小时前
LNMP 一键安装包部署 Django 项目
后端·django·1024程序员节
newxtc4 小时前
【江苏政务服务网-注册_登录安全分析报告】
人工智能·安全·yolo·政务·1024程序员节·安全爆破
上去我就QWER4 小时前
Python下常用开源库
python·1024程序员节
Bryce李小白4 小时前
Flutter中Key的作用以及应用场景
1024程序员节
黄思搏4 小时前
红黑树 - Red-Black Tree 原理与 C# 实现
数据结构·1024程序员节
云边有个稻草人4 小时前
KingbaseES数据库:异构多活构建极致容灾
1024程序员节