首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Tomcat 系統架構與核心設計模式深度解析(上):總體架構、生命周期管理與連接器原理

     編輯:Java 綜合教學

前言:剖析 Tomcat 的「心臟」與「骨架」

Apache Tomcat 作為最流行的 Servlet 容器,其架構設計蘊含豐富的設計模式智慧。本系列分兩部分,第一部分聚焦 總體架構、組件生命周期管理、Connector 請求處理線程模型、Container 容器層級協作,還原 Tomcat 如何高效分發請求、支撐高併發。

一、Tomcat 總體架構:雙核心組件與 Service/Server 包裝

1. 核心組件關係圖

Server (生命周期總控)
 └─ Service (對外服務單元)
      ├─ Connector[] (多連接器:HTTP/AJP/HTTPS...)
      │    └─ 職責:網絡通信、請求/響應對象構建、線程調度
      └─ Container (單容器:Engine)
           └─ 職責:Servlet 請求處理、多級子容器管理

關鍵點:

  • Connector 可替換:支援 BIO/NIO/APR 多種 I/O 模型,適應不同場景。
  • 一個 Service = 多 Connector + 一 Container:同一容器可同時服務不同端口/協議。
  • Server 管理多 Service:提供統一啟停、JMX 管理入口。

2. Service 接口與 StandardService 實現

public interface Service {
    void addConnector(Connector connector);
    void removeConnector(Connector connector);
    void setContainer(Container container);
    Container getContainer();
    String getName();
    // 生命周期方法在 Lifecycle 接口中定義
}

StandardService 實現了 Service + Lifecycle + 事件監聽機制,核心邏輯:

  • setContainer:雙向綁定 Container↔Service,同步綁定到所有 Connector,管理 Container 生命周期。
  • addConnector:雙向綁定 Connector↔Service/Container,動態數組擴容(System.arraycopy 實現類 ArrayList 擴容),初始化並啟動 Connector。

3. Server 與 StandardServer

StandardServer 管理 Service[] 數組,同樣採用動態擴容數組,實現 Lifecycle 統一啟停所有 Service。Tomcat 5+ 引入 MBeanRegistration 整合 JMX 管理。

二、組件生命線:Lifecycle 接口與事件驅動模型

1. Lifecycle 接口定義

public interface Lifecycle {
    void start() throws LifecycleException;
    void stop() throws LifecycleException;
    // 事件監聽
    void addLifecycleListener(LifecycleListener listener);
    void removeLifecycleListener(LifecycleListener listener);
    void fireLifecycleEvent(String type, Object data);
}

設計模式:模板方法模式(定義啟停骨架)+ 觀察者模式(生命周期事件通知)。

2. StandardServer 啟停流程

public void start() {
    if (started) return;
    fireLifecycleEvent(BEFORE_START_EVENT, null);
    fireLifecycleEvent(START_EVENT, null);
    started = true;
    for (Service service : services) {
        if (service instanceof Lifecycle) ((Lifecycle)service).start(); // 遞歸啟動
    }
    fireLifecycleEvent(AFTER_START_EVENT, null);
}

public void stop() {
    if (!started) return;
    fireLifecycleEvent(BEFORE_STOP_EVENT, null);
    fireLifecycleEvent(STOP_EVENT, null);
    started = false;
    for (Service service : services) {
        if (service instanceof Lifecycle) ((Lifecycle)service).stop(); // 遞歸停止
    }
    fireLifecycleEvent(AFTER_STOP_EVENT, null);
}

所有組件(Server/Service/Connector/Container/Valve...)均實現 Lifecycle,形成樹狀生命周期管理,啟動時自頂向下,停止時自底向上。

三、Connector 組件:網絡 I/O 與線程調度核心

1. 核心職責

  1. 接收 Socket 連接
  2. 封裝 Request/Response 對象
  3. 線程調度:將請求分發給 Container 處理

2. Tomcat 5 默認 Coyote 架構拆分

Connector (對外接口)
 └─ Processor (協議處理:Http11Processor)
      └─ Protocol (具體協議邏輯)

自定義 Request/Response 隔離 Servlet API,便於協議擴展。

3. 線程模型演進(以 HttpConnector 為例)

// HttpConnector.start() 創建最小處理器池
while (curProcessors < minProcessors) {
    HttpProcessor processor = newProcessor();
    recycle(processor); // 放入可用池
}

// HttpProcessor.assign(Socket) - 生產者喚醒消費者
synchronized void assign(Socket socket) {
    while (available) wait(); // 等待空閒
    this.socket = socket;
    available = true;
    notifyAll(); // 喚醒 run() 處理
}

// HttpProcessor.run() - 消費者循環
public void run() {
    while (!stopped) {
        Socket socket = await(); // 從可用池獲取
        process(socket); // 解析請求、調用 Container
        connector.recycle(this); // 歸還池
    }
}

本質:生產者-消費者模式 + 對象池模式。available 旗標充當信號量,wait/notifyAll 實現線程協作。recycle 避免頻繁創建 Processor 對象。

4. 關鍵流程:process() → Container.invoke()

private void process(Socket socket) {
    // 1. 輸入流包裝 SocketInputStream
    // 2. 解析請求行、Headers
    // 3. 構建 Request/Response
    // 4. 關鍵調用
    if (ok) connector.getContainer().invoke(request, response); // 轉交 Container
    // 5. 輸出響應、關閉流
}

四、Servlet 容器 Container:責任鏈模式的四級容器

1. 容器層級與職責

層級組件職責對應配置
1Engine頂級容器,代表完整 Servlet 引擎,管理多個 Host<Engine>
2Host虛擬主機,管理多個 Web 應用,部署/展開 WAR<Host>
3ContextWeb 應用上下文,管理 Servlet 實例,解析 web.xml<Context>
4Wrapper單個 Servlet 封裝,負責加載、初始化、調用、銷毀<servlet> in web.xml

父子關係:Engine → Host → Context → Wrapper

2. 請求處理流水線:Valve 與 Pipeline

  • 每個容器擁有一個 Pipeline(管道),包含多個 Valve(閥門)
  • 請求在管道中順序通過各 Valve,最後由 StandardEngineValve / StandardHostValve / StandardContextValve / StandardWrapperValve 將請求傳遞給子容器
  • server.xml 中可自定義 Valve(如訪問日志、請求傾印)
<Engine>
  <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
  <Host>
    <Valve className="org.apache.catalina.valves.FastCommonAccessLogValve" .../>
  </Host>
</Engine>

3. 子容器路由:Tomcat 5+ 基於 Request 映射

請求處理時序:

  1. Engine:根據 Host header 選擇 Host,綁定到 request
  2. Host:根據 URL path 選擇 Context,綁定到 request
  3. Context:根據 URL pattern 選擇 Wrapper,綁定到 request
  4. Wrapper:調用 Servlet.service()

所有路由信息存儲在 request 對象中,避免了早期 Mapper 集中式路由的性能瓶頸。

4. 關鍵容器源碼亮點

  • StandardEngine:addChild 只接受 Host;setParent 拋異常(頂級無父)。
  • StandardHost:實現 Deployer 接口,負責 WAR 部署/展開/啟動/停止。
  • StandardContext:
    • start():初始化資源、啟動子容器、啟動 Pipeline。
    • backgroundProcess()(後台線程周期調用):reloadable=true 時檢測類文件變更,觸發 reload()(stop→start)熱部署。
  • StandardWrapper:
    • loadServlet():類加載 → 實例化 → servlet.init() → 可選預載入 service()。
    • 包裝 ServletConfig 為 StandardWrapperFacade,限制 Servlet 訪問容器信息範圍。
    • StandardWrapperValve:調用 Filter 鏈 → servlet.service()。

五、其他核心組件速覽

  • Security:Realm、Principal、LoginConfig 實現認證授權
  • Logger:日志系統,支援多種實現
  • Session Manager:StandardManager/PersistentManager,支援集群 Session 複製
  • Naming:JNDI 資源查找
  • MBeans:JMX 管理監控

結語與下篇預告

本文梳理了 Tomcat 的宏觀架構、生命周期體系、Connector 線程模型、Container 四級容器與 Valve/Pipeline 責任鏈。下篇將深入剖析 Tomcat 中經典設計模式的具體應用場景(觀察者、命令、適配器、狀態、外觀等),並結合源碼展示模式如何解決具體架構難題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved