大飛帶你深入理解Tomcat(七)

weixin_34075551發表於2018-07-03

作者:叩丁狼教育王一飛,高階講師。轉載請註明出處。

經過前幾篇的tomcat分解,大體能理解tomcat操作原理,那麼真實的tomcat又是一個怎麼的架構呢?本篇我們站在上帝角度來看下tomcat整個系統結構。


11401799-c84262cb4aecf125.png
tomcat元件結構

下面是上圖各元件的介紹:

Server

最頂級元件,程式碼著tomcat例項,在JVM有且僅有一份。引入事件處理機制,方便Server在生命週期不同階段處理不同邏輯。引入GlobalNamingResources元件,為JNDI提供支援。

Service

tomcat功能服務的抽象,一個server元件中至少有一個service, 是請求從發起到響應所有參與元件集合體。分為2個核心部分:Connector元件和Container(Engine/Host/Context/Wrapper統稱)元件。注意,一個Service包含若干個Connector元件,用於處理基於不同通訊協議的連線相關事情, 比如HTTP協議、AJP協議等連線。而一個Service只能擁有一個Engine元件。

Connector

負責接收客戶端連線並接收訊息報文,簡單講就是將socket轉換成Reqeust跟Response物件,然後交給Engine容器處理。Connector元件包含的模組
》協議模組(Protocol)
識別客戶端請求是基於什麼協議,目前tomcat支援HTTP協議、HTTPS協議,HTTP2協議和AJP協議,對應的處理類Http11AprProtocol類,Http2Protocol類,AjpAprProtocol類
》Acceptor元件
用於監聽連線埠,當請求到來時,直接丟入Executor執行緒池統一處理。
》Processor元件
處理請求(分析協議,獲取請求資料,封裝請求物件等),將處理結果(請求物件)傳入到Engine容器。
tomcat同時支援網路IO方式:同步阻塞(BIO), 同步非阻塞(NIO), 非同步非阻塞(NIO2/AIO), 通用IO操作規範(APR), 其中Tomcat8.5之後拋棄對BIO的支援。
》Mapper元件
路徑對映元件,也可以稱之路徑路由。通過解析url的地址,對映到具體serlvet類。
》CoyoteAdaptor元件
Connector元件與Engine元件連線的介面卡。

Container

tomcat容器的統稱,tomcat中有4個級別的容器,分別是Engine,Host,Context, Wrapper。Connector元件接收與處理客戶端發起的請求,將處理結果傳入tomcat容器,以求進一步處理。如下圖:


11401799-bb86a9a20899a2ba.png
簡單流程圖
Engine

頂層的容器, 代表一個全域性 Servlet 引擎,負責接收connector包裝的請求。每一service只能有一個Engine元件,而Engine元件可以包含多個Host元件。除了Host元件外,Engin還包含其他元件
》Listener:監聽tomcat生命週期中關於Engine容器相關的工作, 比如建立,銷燬等
》AccessLog元件:記錄客戶端訪問日誌
》Cluster元件:提供叢集功能
》PipeLine元件:Engine容器對請求進行處理管道
》Realm元件:提供Engine容器級別的許可權校驗資訊物件

Host

Engine容器的子容器,表示一個虛擬主機。是根據URL地址中的主機(IP/域名,比如localhost)抽象而來。一個Engine容器可以包含若干個Host容器,而一個Host容器可以包含若干跟context容器。其他元件跟Egine子元件一樣,這裡不多說

Context

對應一個web應用程式,是對於web專案的抽象,負責將web專案所有元件轉成tomcat能操作的容器元件。包含多個Wrapper元件。
》Loader元件:Web應用載入器,用於載入web資源。
》Manager元件:會話管理器,管理部署到tomcat中的web容器會話。比如維護會話的生成、更新、銷燬
》NamingResource元件:命名資源,完成Tomcat server.xml和web應用context.xml資源與屬性的對映
》Mapper元件:Servlet對映器

Wrapper

tomcat中最下的容器物件,與之對應的是servlet, 一個Wrapper對應一個Servlet。它包含3個子元件:
》Servlet元件:web專案處理邏輯的servlet
》ServletPool元件:Servlet物件池,如果servlet實現SingleThreadModel介面時,Wrapper會建立一個Servlet物件池,保證Servelt訪問執行緒安全。
》PipeLine元件:Wrapper容器對請求進行處理管道

以一個案例來總結

假設在tomcat中部署一個web專案:

<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <GlobalNamingResources>...</GlobalNamingResources>
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm"></Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <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" />        
          <Context path="" docBase="xxx/helloApp/webapp" > 
        </Context>                                                        
      </Host>
    </Engine>
  </Service>
</Server>

1>在tomcat根/conf/server.xml檔案上配置一個

 <Context path="" docBase="xxx/helloApp/webapp" ></Context>     

2>啟動tomcat,Connector元件接收器(Accoptor)監聽server.xml配置的8080埠,當然其他埠(8009)也監聽。目前關注8080埠

3>在瀏覽器位址列中輸入http://localhost:8080/hello 回車

4>瀏覽器發起請求(發起socket連線),Accoptor接收器接收到連線,將連線封裝到任務執行緒,丟到執行緒池(Executor)處理.

5>執行緒池(Exceutor)發現任務佇列中有執行緒任務, 馬上可以執行響應任務,
1) 先判斷髮起連線的協議(Protocol):此處為Http1.1協議
2) 根據協議呼叫不同連線處理元件(Processor):此處呼叫的是Http11Processor元件
Http11Processor 元件開始解析HTTP請求頭,請求行,請求體,將解析結果封裝成Request物件,傳入到容器中。

6>Mapper元件根據HTTP請求行中URL屬性以及Host請求頭,匹配哪個Host容器,哪個Context容器,哪個Wraper容器處理請求。這一步結合專案配置的web.xml檔案可以找到具體的servlet

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>cn.wolfcode.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

7>CoyoteAdaptor元件是Connector跟Container連線橋樑,將前幾步建立的請求Request物件與響應Response物件傳到Engine容器,呼叫Engine容器的Pipeline管道執行其他額外的操作。

8>Engine容器執行容器中定義的各種Pipeline管道,最後執行Host容器的Pipeline管道,將Reqeust跟Response物件傳入到Host容器。

9>Host容器執行容器中定義的各種Pipeline管道,最後執行Host容器的Pipeline管道,將Reqeust跟Response物件傳入到Context容器。

10>Context容器執行容器中定義的各種Pipeline管道,最後執行Host容器的Pipeline管道,將Reqeust跟Response物件傳入到Wrapper容器。
11>Wrapper容器呼叫其對應的Servlet中的service方法,處理請求邏輯,然後將結果響應給瀏覽器。
下面是上述請求的草圖:


11401799-67e9e6eeeaaaf650.png
請求流程圖
807144-c959b48672873097.jpeg
WechatIMG9.jpeg

相關文章