Tomcat——Tomcat系統(tǒng)架構(gòu)與原理分析

一、簡介

Tomcat服務(wù)器是一個免費的開放源碼的Web應(yīng)用服務(wù)器,目前是應(yīng)用比較廣泛的。

從Tomcat的7.0版本開始支持Servlet3.0規(guī)范規(guī)范,可以支持我們開發(fā)過程中不再配置web.xml。

瀏覽器訪問服務(wù)器的流程

瀏覽器訪問服務(wù)器使用的是http協(xié)議,http是應(yīng)用層協(xié)議,用于定義數(shù)據(jù)通信的格式,具體的數(shù)據(jù)傳輸使用的是TCP/IP協(xié)議。

  • 1、用戶向瀏覽器發(fā)起http請求。
  • 2、瀏覽器接收到用戶請求,向服務(wù)器發(fā)起TCP連接請求。
  • 3、服務(wù)器接收到瀏覽器請求,并建立TCP連接。
  • 4、瀏覽器生成HTTP數(shù)據(jù)包,向服務(wù)器發(fā)送數(shù)據(jù)包。
  • 5、服務(wù)器收到瀏覽器發(fā)送過來的數(shù)據(jù)包必能解析,執(zhí)行請求對應(yīng)的具體邏輯,將返回數(shù)據(jù)組裝成http格式包并返回。
  • 6、瀏覽器接收到服務(wù)器返回的http的數(shù)據(jù)包,解析http數(shù)據(jù)包,通過瀏覽器將相應(yīng)靜態(tài)資源呈現(xiàn)給用戶。
  • 1、用戶通過瀏覽器進行了一個操作,比如輸入網(wǎng)址并回車,或者是點擊鏈接,接著瀏覽 器獲取了這個事件。
  • 2、瀏覽器向服務(wù)端發(fā)出TCP連接請求。
  • 3、服務(wù)程序接受瀏覽器的連接請求,并經(jīng)過TCP三次握手建立連接。
  • 4、瀏覽器將請求數(shù)據(jù)打包成一個HTTP協(xié)議格式的數(shù)據(jù)包。
  • 5、瀏覽器將該數(shù)據(jù)包推入網(wǎng)絡(luò),數(shù)據(jù)包經(jīng)過網(wǎng)絡(luò)傳輸,最終達到端服務(wù)程序。
  • 6、服務(wù)端程序拿到這個數(shù)據(jù)包后,同樣以HTTP協(xié)議格式解包,獲取到客戶端的意圖。
  • 7、得知客戶端意圖后進行處理,比如提供靜態(tài)文件或者調(diào)用服務(wù)端程序獲得動態(tài)結(jié)果。
  • 8、服務(wù)器將響應(yīng)結(jié)果(可能是HTML或者圖片等)按照HTTP協(xié)議格式打包。
  • 9、服務(wù)器將響應(yīng)數(shù)據(jù)包推入網(wǎng)絡(luò),數(shù)據(jù)包經(jīng)過網(wǎng)絡(luò)傳輸最終達到到瀏覽器。
  • 10、瀏覽器拿到數(shù)據(jù)包后,以HTTP協(xié)議的格式解包,然后解析數(shù)據(jù),假設(shè)這里的數(shù)據(jù)是 HTML。
  • 11、瀏覽器將HTML文件展示在頁面上。

那我們想要探究的Tomcat作為一個HTTP服務(wù)器,主要是接受連接、解析請求數(shù)據(jù)、處理請求和發(fā)送響應(yīng)這幾個步驟。

Http服務(wù)器請求處理

瀏覽器發(fā)給服務(wù)端的是一個HTTP格式的請求,HTTP服務(wù)器收到這個請求后,需要調(diào)用服務(wù)端程序來處理,所謂的服務(wù)端程序就是寫的Java類,一般來說不同的請求需要由不同 的Java類來處理。

HTTP服務(wù)器不直接調(diào)用業(yè)務(wù)類,而是把請求交給容器來處理,容器通過Servlet接口調(diào)用業(yè)務(wù)類。因此Servlet接口和Servlet容器的出現(xiàn),達到了HTTP服務(wù)器與 業(yè)務(wù)類解耦的目的。而Servlet接口和Servlet容器這一整套規(guī)范叫作Servlet規(guī)范。 Tomcat按照Servlet規(guī)范的要求實現(xiàn)了Servlet容器,同時它們也具有HTTP服務(wù)器的功能。作為Java程序員,如果我們要實現(xiàn)新的業(yè)務(wù)功能,只需要實現(xiàn)一個Servlet,并把它注冊到Tomcat(Servlet容器)中,剩下的事情就由Tomcat幫我們處理了。

Servlet容器工作流程

為了解耦,HTTP服務(wù)器不直接調(diào)用Servlet,而是把請求交給Servlet容器來處理。當(dāng)客戶請求某個資源時,HTTP服務(wù)器會用一個ServletRequest對象把客戶的請求信息封 裝起來,然后調(diào)用Servlet容器的service方法,Servlet容器拿到請求后,根據(jù)請求的URL 和Servlet的映射關(guān)系,找到相應(yīng)的Servlet,如果Servlet還沒有被加載,就用反射機制創(chuàng) 建這個Servlet,并調(diào)用Servlet的init方法來完成初始化,接著調(diào)用Servlet的service方法 來處理請求,把ServletResponse對象返回給HTTP服務(wù)器,HTTP服務(wù)器會把響應(yīng)發(fā)送給 客戶端。

二、Tomcat整體架構(gòu)

我們知道如果要設(shè)計一個系統(tǒng),首先是要了解需求,我們已經(jīng)了解了Tomcat要實現(xiàn)兩個核心功能:

  • 1、處理Socket連接,負(fù)責(zé)網(wǎng)絡(luò)字節(jié)流與Request和Response對象的轉(zhuǎn)化。
  • 2、加載和管理Servlet,以及具體處理Request請求。

因此Tomcat設(shè)計了兩個核心組件連接器(Connector)和容器(Container)來分別做這兩件事情。連接器負(fù)責(zé)對外交流,容器負(fù)責(zé)內(nèi)部處理。

2.1、Tomcat連接器組件Coyote

2.1.1、連接器 - Coyote

Coyote 是Tomcat的連接器框架的名稱 , 是Tomcat服務(wù)器提供的供客戶端訪問的外部接口??蛻舳送ㄟ^Coyote與服務(wù)器建立連接、發(fā)送請求并接受響應(yīng) 。

  • 1、Coyote 封裝了底層的網(wǎng)絡(luò)通信(Socket 請求及響應(yīng)處理),為Catalina 容器提供了統(tǒng)一 的接口,使Catalina 容器與具體的請求協(xié)議及IO操作方式完全解耦。
  • 2、Coyote 將Socket 輸 入轉(zhuǎn)換封裝為 Request 對象,交由Catalina 容器進行處理,處理請求完成后,Catalina 通 過Coyote 提供的Response 對象將結(jié)果寫入輸出流 。
  • 3、Coyote 作為獨立的模塊,只負(fù)責(zé)具體協(xié)議和IO的相關(guān)操作,與Servlet 規(guī)范實現(xiàn)沒有直接關(guān)系,因此即便是Request 和 Response 對象也并未實現(xiàn)Servlet規(guī)范對應(yīng)的接口,而是在Catalina中將他們進一步封裝為ServletRequest和ServletResponse 。

2.1.2、IO模型與協(xié)議

在Coyote中,Tomcat支持的多種I/O模型和應(yīng)用層協(xié)議,具體包含哪些IO模型和應(yīng)用層協(xié)議,請看下表:
Tomcat 支持的IO模型(自8.5/9.0 版本起,Tomcat 移除了 對 BIO 的支持):

IO模型 描述
NIO 非阻塞I/O,采用Java NIO類庫實現(xiàn)。
NIO2 異步I/O,采用JDK 7最新的NIO2類庫實現(xiàn)。
APR 采用Apache可移植運行庫實現(xiàn),是C/C++編寫的本地庫。如果選擇該方 案,需要單獨安裝APR庫。

Tomcat 支持的應(yīng)用層協(xié)議 :

應(yīng)用層協(xié)議 描述
HTTP/1.1 這是大部分Web應(yīng)用采用的訪問協(xié)議。
AJP 用于和Web服務(wù)器集成(如Apache),以實現(xiàn)對靜態(tài)資源的優(yōu)化以及 集群部署,當(dāng)前支持AJP/1.3。
HTTP/2 HTTP 2.0大幅度的提升了Web性能。下一代HTTP協(xié)議 , 自8.5以及9.0 版本之后支持。

協(xié)議分層 :


在 8.0 之前 , Tomcat 默認(rèn)采用的I/O方式為 BIO , 之后改為 NIO。 無論 NIO、NIO2 還是 APR, 在性能方面均優(yōu)于以往的BIO。 如果采用APR, 甚至可以達到 Apache HTTP Server 的影響性能。

Tomcat為了實現(xiàn)支持多種I/O模型和應(yīng)用層協(xié)議,一個容器可能對接多個連接器,就好比一個房間有多個門。但是單獨的連接器或者容器都不能對外提供服務(wù),需要把它們組裝起來才能工作,組裝后這個整體叫作Service組件。這里請你注意,Service本身沒有做什么重要的事情,只是在連接器和容器外面多包了一層,把它們組裝在一起。Tomcat內(nèi)可能有多個Service,這樣的設(shè)計也是出于靈活性的考慮。通過在Tomcat中配置多個Service,可以實現(xiàn)通過不同的端口號來訪問同一臺機器上部署的不同應(yīng)用。

2.1.3、 連接器組件

連接器中的各個組件的作用如下:

EndPoint
  • 1、EndPoint : Coyote 通信端點,即通信監(jiān)聽的接口,是具體Socket接收和發(fā)送處理 器,是對傳輸層的抽象,因此EndPoint用來實現(xiàn)TCP/IP協(xié)議的。
  • 2、Tomcat 并沒有EndPoint 接口,而是提供了一個抽象類AbstractEndpoint , 里面定 義了兩個內(nèi)部類:Acceptor和SocketProcessor。Acceptor用于監(jiān)聽Socket連接請求。 SocketProcessor用于處理接收到的Socket請求,它實現(xiàn)Runnable接口,在Run方法里 調(diào)用協(xié)議處理組件Processor進行處理。為了提高處理能力,SocketProcessor被提交到 線程池來執(zhí)行。而這個線程池叫作執(zhí)行器(Executor),我在后面的專欄會詳細(xì)介紹 Tomcat如何擴展原生的Java線程池。
Processor

Processor:Coyote 協(xié)議處理接口 ,如果說EndPoint是用來實現(xiàn)TCP/IP協(xié)議的,那么 Processor用來實現(xiàn)HTTP協(xié)議,Processor接收來自EndPoint的Socket,讀取字節(jié)流解 析成Tomcat Request和Response對象,并通過Adapter將其提交到容器處理, Processor是對應(yīng)用層協(xié)議的抽象。

ProtocolHandler

ProtocolHandler: Coyote 協(xié)議接口, 通過Endpoint 和 Processor , 實現(xiàn)針對具體協(xié) 議的處理能力。Tomcat 按照協(xié)議和I/O 提供了6個實現(xiàn)類 : AjpNioProtocol , AjpAprProtocol, AjpNio2Protocol , Http11NioProtocol ,Http11Nio2Protocol , Http11AprProtocol。我們在配置tomcat/conf/server.xml 時 , 至少要指定具體的 ProtocolHandler , 當(dāng)然也可以指定協(xié)議名稱 , 如 : HTTP/1.1 ,如果安裝了APR,那么 將使用Http11AprProtocol , 否則使用 Http11NioProtocol 。

Adapter

由于協(xié)議不同,客戶端發(fā)過來的請求信息也不盡相同,Tomcat定義了自己的Request類 來“存放”這些請求信息。ProtocolHandler接口負(fù)責(zé)解析請求并生成Tomcat Request類。 但是這個Request對象不是標(biāo)準(zhǔn)的ServletRequest,也就意味著,不能用Tomcat Request作為參數(shù)來調(diào)用容器。Tomcat設(shè)計者的解決方案是引入CoyoteAdapter,這是 適配器模式的經(jīng)典運用,連接器調(diào)用CoyoteAdapter的Sevice方法,傳入的是Tomcat Request對象,CoyoteAdapter負(fù)責(zé)將Tomcat Request轉(zhuǎn)成ServletRequest,再調(diào)用容 器的Service方法。

2.3、容器 - Catalina

Tomcat是一個由一系列可配置的組件構(gòu)成的Web容器,而Catalina是Tomcat的servlet容器。Catalina是Servlet容器實現(xiàn),包含了之前講到的所有的容器組件,以及后續(xù)涉及到 的安全、會話、集群、管理等Servlet 容器架構(gòu)的各個方面。它通過松耦合的方式集成 Coyote,以完成按照請求協(xié)議進行數(shù)據(jù)讀寫。同時,它還包括我們的啟動入口、Shell程 序等。

2.3.1、Catalina依賴關(guān)系

從另一個角度來說,Tomcat本質(zhì)上就是一款Servlet容器,因為Catalina才是Tomcat的核心,其他模塊都是為Catalina提供支撐的。比如:通過Coyote模塊提供連接通信,Jasper模塊提供JSP引擎,Naming提供JNDI服務(wù),Juli提供日志服務(wù)。

2.3.2、Catalina 結(jié)構(gòu)

Catalina 的主要組件結(jié)構(gòu)如下:


如上圖所示,Catalina負(fù)責(zé)管理Server,而Server表示著整個服務(wù)器。Server下面有多個 服務(wù)Service,每個服務(wù)都包含著多個連接器組件Connector(Coyote 實現(xiàn))和一個容器 組件Container。在Tomcat 啟動的時候, 會初始化一個Catalina的實例。

Catalina 各個組件的職責(zé):

組件 職責(zé)
Catalina 負(fù)責(zé)解析Tomcat的配置文件 , 以此來創(chuàng)建服務(wù)器Server組件,并根據(jù) 命令來對其進行管理
Server 服務(wù)器表示整個Catalina Servlet容器以及其它組件,負(fù)責(zé)組裝并啟動 Servlet引擎,Tomcat連接器。Server通過實現(xiàn)Lifecycle接口,提供了 一種優(yōu)雅的啟動和關(guān)閉整個系統(tǒng)的方式
Service 服務(wù)是Server內(nèi)部的組件,一個Server包含多個Service。它將若干個 Connector組件綁定到一個Container(Engine)上
Connector 連接器,處理與客戶端的通信,它負(fù)責(zé)接收客戶請求,然后轉(zhuǎn)給相關(guān) 的容器處理,最后向客戶返回響應(yīng)結(jié)果
Container 容器,負(fù)責(zé)處理用戶的servlet請求,并返回對象給web用戶的模塊

2.3.3、 Container結(jié)構(gòu)

Tomcat設(shè)計了4種容器,分別是Engine、Host、Context和Wrapper。這4種容器不是平行關(guān)系,而是父子關(guān)系。, Tomcat通過一種分層的架構(gòu),使得Servlet容器具有很好的靈 活性。


各個組件的含義 :

容器 描述
Engine 表示整個Catalina的Servlet引擎,用來管理多個虛擬站點,一個Service 最多只能有一個Engine,但是一個引擎可包含多個Host
Host 代表一個虛擬主機,或者說一個站點,可以給Tomcat配置多個虛擬主 機地址,而一個虛擬主機下可包含多個Context
Context 表示一個Web應(yīng)用程序, 一個Web應(yīng)用可包含多個Wrapper
Wrapper 表示一個Servlet,Wrapper 作為容器中的最底層,不能包含子容器

我們也可以再通過Tomcat的server.xml配置文件來加深對Tomcat容器的理解。Tomcat 采用了組件化的設(shè)計,它的構(gòu)成組件都是可配置的,其中最外層的是Server,其他組件按照一定的格式要求配置在這個頂層容器中。

<Server>
    <Service>
        <Connector>
        </Connector>
        <Engine>
            <Host>
                <Context></Context>
            </Host>
        </Engine>
    </Service>
</Server>

這些容器具有父子關(guān)系,形成一個樹形結(jié)構(gòu),Tomcat通過組合模式來管理這些容器。
具體實現(xiàn)方法是,所有容器組件都實現(xiàn)了Container接口,因此組合模
式可以使得用戶對單容器對象和組合容器對象的使用具有一致性。這里單容器對象指的
是最底層的Wrapper,組合容器對象指的是上面的Context、Host或者Engine。

Container 接口中提供了以下方法(截圖中知識一部分方法) :


在上面的接口看到了getParent、SetParent、addChild和removeChild等方法。
Container接口擴展了LifeCycle接口,LifeCycle接口用來統(tǒng)一管理各組件的生命周期。

參考:
https://blog.csdn.net/qq_37551917/article/details/119681753

https://www.cnblogs.com/yifengGG/p/13124816.html

https://www.cnblogs.com/prliu/p/14298835.html

https://www.pianshen.com/article/75801608257/

https://www.cnblogs.com/sunlightlee/p/10994281.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容