淄博網(wǎng)站建設(shè)相關(guān)文章如何快速推廣
利刃出鞘_Tomcat 核心原理解析(二)
一、 Tomcat專題 - Tomcat架構(gòu) - HTTP工作流程
1、Http 工作原理
HTTP 協(xié)議:是瀏覽器與服務(wù)器之間的數(shù)據(jù)傳送協(xié)議。作為應(yīng)用層協(xié)議,HTTP 是基于 TCP/IP 協(xié)議來(lái)傳遞數(shù)據(jù)的(HTML文件、圖片、查詢結(jié)果等),HTTP 協(xié)議不涉及數(shù)據(jù)包(Packet)傳輸,主要規(guī)定了客戶端和服務(wù)器之間的通信格式。
2、HTTP 協(xié)議流程圖:
3、HTTP 過(guò)程:
1) 用戶通過(guò)瀏覽器進(jìn)行了一個(gè)操作,比如輸入網(wǎng)址并回車,或者是點(diǎn)擊鏈接,接著瀏覽
器獲取了這個(gè)事件。
2) 瀏覽器向服務(wù)端發(fā)出TCP連接請(qǐng)求。
3) 服務(wù)程序接受瀏覽器的連接請(qǐng)求,并經(jīng)過(guò)TCP三次握手建立連接。
4) 瀏覽器將請(qǐng)求數(shù)據(jù)打包成一個(gè)HTTP協(xié)議格式的數(shù)據(jù)包。
5) 瀏覽器將該數(shù)據(jù)包推入網(wǎng)絡(luò),數(shù)據(jù)包經(jīng)過(guò)網(wǎng)絡(luò)傳輸,最終達(dá)到端服務(wù)程序。
6) 服務(wù)端程序拿到這個(gè)數(shù)據(jù)包后,同樣以HTTP協(xié)議格式解包,獲取到客戶端的意圖。
7) 得知客戶端意圖后進(jìn)行處理,比如提供靜態(tài)文件或者調(diào)用服務(wù)端程序獲得動(dòng)態(tài)結(jié)果。
8) 服務(wù)器將響應(yīng)結(jié)果(可能是HTML或者圖片等)按照HTTP協(xié)議格式打包。
9) 服務(wù)器將響應(yīng)數(shù)據(jù)包推入網(wǎng)絡(luò),數(shù)據(jù)包經(jīng)過(guò)網(wǎng)絡(luò)傳輸最終達(dá)到到瀏覽器。
10) 瀏覽器拿到數(shù)據(jù)包后,以HTTP協(xié)議的格式解包,然后解析數(shù)據(jù),假設(shè)這里的數(shù)據(jù)是
HTML。
11) 瀏覽器將HTML文件展示在頁(yè)面上。
那我們想要探究的Tomcat作為一個(gè)HTTP服務(wù)器,在這個(gè)過(guò)程中都做了些什么事情呢?主
要是接受連接、解析請(qǐng)求數(shù)據(jù)、處理請(qǐng)求和發(fā)送響應(yīng)這幾個(gè)步驟。
二、 Tomcat專題 - Tomcat架構(gòu) - Tomcat整體架構(gòu)
1、Http服務(wù)器請(qǐng)求處理
瀏覽器發(fā)給服務(wù)端的是一個(gè)HTTP格式的請(qǐng)求,HTTP服務(wù)器收到這個(gè)請(qǐng)求后,需要調(diào)用服務(wù)端程序來(lái)處理,所謂的服務(wù)端程序就是你寫的Java類,一般來(lái)說(shuō)不同的請(qǐng)求需要由不同的 Java 類來(lái)處理。
1) 圖1 , 表示HTTP服務(wù)器直接調(diào)用具體業(yè)務(wù)類,它們是緊耦合的。
2) 圖2,HTTP服務(wù)器不直接調(diào)用業(yè)務(wù)類,而是把請(qǐng)求交給容器來(lái)處理,容器通過(guò)Servlet接口調(diào)用業(yè)務(wù)類。因此Servlet接口和Servlet容器的出現(xiàn),達(dá)到了HTTP服務(wù)器與業(yè)務(wù)類解耦的目的。而Servlet接口和Servlet容器這一整套規(guī)范叫作Servlet規(guī)范。
Tomcat 按照 Servlet 規(guī)范的要求實(shí)現(xiàn)了 Servlet 容器,同時(shí)它們也具有HTTP服務(wù)器的功能。作為Java程序員,如果我們要實(shí)現(xiàn)新的業(yè)務(wù)功能,只需要實(shí)現(xiàn)一個(gè)Servlet,并把它注冊(cè)到Tomcat(Servlet容器)中,剩下的事情就由Tomcat幫我們處理了。
2、Servlet 容器工作流程
為了解耦,HTTP服務(wù)器不直接調(diào)用Servlet,而是把請(qǐng)求交給Servlet容器來(lái)處理,那
Servlet容器又是怎么工作的呢?
當(dāng)客戶請(qǐng)求某個(gè)資源時(shí),HTTP服務(wù)器會(huì)用一個(gè)ServletRequest對(duì)象把客戶的請(qǐng)求信息封裝起來(lái),然后調(diào)用Servlet容器的service方法,Servlet容器拿到請(qǐng)求后,根據(jù)請(qǐng)求的URL和Servlet的映射關(guān)系,找到相應(yīng)的Servlet,如果Servlet還沒(méi)有被加載,就用反射機(jī)制創(chuàng)建這個(gè)Servlet,并調(diào)用Servlet的init方法來(lái)完成初始化,接著調(diào)用Servlet的service方法來(lái)處理請(qǐng)求,把ServletResponse對(duì)象返回給HTTP服務(wù)器,HTTP服務(wù)器會(huì)把響應(yīng)發(fā)送給
客戶端。
3、Tomcat整體架構(gòu)
如果要設(shè)計(jì)一個(gè)系統(tǒng),首先是要了解需求,了解 Tomcat 要實(shí)現(xiàn)兩個(gè)核心功能:
1) 處理Socket連接,負(fù)責(zé)網(wǎng)絡(luò)字節(jié)流與Request和Response對(duì)象的轉(zhuǎn)化。
2) 加載和管理Servlet,以及具體處理Request請(qǐng)求。
因此 Tomcat 設(shè)計(jì)了兩個(gè)核心組件連接器(Connector)和容器(Container)來(lái)分別做這兩件事情。連接器負(fù)責(zé)對(duì)外交流,容器負(fù)責(zé)內(nèi)部處理。
三、 Tomcat專題 - Tomcat架構(gòu) - Coyote連接器架構(gòu)介紹
1、連接器 - Coyote 架構(gòu)介紹
-
Coyote 是 Tomcat 的連接器框架的名稱 , 是Tomcat服務(wù)器提供的供客戶端訪問(wèn)的外部接口??蛻舳送ㄟ^(guò) Coyote 與服務(wù)器建立連接、發(fā)送請(qǐng)求并接受響應(yīng) 。
-
Coyote 封裝了底層的網(wǎng)絡(luò)通信(Socket 請(qǐng)求及響應(yīng)處理),為 Catalina 容器提供了統(tǒng)一的接口,使 - Catalina 容器與具體的請(qǐng)求協(xié)議及IO操作方式完全解耦。Coyote 將 Socket 輸入轉(zhuǎn)換封裝為 Request 對(duì)象,交由Catalina 容器進(jìn)行處理,處理請(qǐng)求完成后, Catalina 通過(guò)Coyote 提供的 Response 對(duì)象將結(jié)果寫入輸出流 。
-
Coyote 作為獨(dú)立的模塊,只負(fù)責(zé)具體協(xié)議和 IO 的相關(guān)操作, 與 Servlet 規(guī)范實(shí)現(xiàn)沒(méi)有直接關(guān)系,因此即便是 Request 和 Response 對(duì)象也并未實(shí)現(xiàn)Servlet規(guī)范對(duì)應(yīng)的接口, 而
是在 Catalina 中將他們進(jìn)一步封裝為 ServletRequest 和 ServletResponse 。
2、 IO 模型與協(xié)議
在 Coyote 中 , Tomcat 支持的多種 I/O 模型和應(yīng)用層協(xié)議,具體包含哪些 IO 模型和應(yīng)用層協(xié)議,請(qǐng)看下表:
1)Tomcat 支持的IO模型(自8.5/9.0 版本起,Tomcat 移除了 對(duì) BIO 的支持):
IO模型 | 描述 | ||
---|---|---|---|
NIO | 非阻塞I/O,采用Java NIO類庫(kù)實(shí)現(xiàn)。 | ||
NIO2 | 異步I/O,采用JDK 7最新的NIO2類庫(kù)實(shí)現(xiàn)。 | ||
APR | 采用Apache可移植運(yùn)行庫(kù)實(shí)現(xiàn),是C/C++編寫的本地庫(kù)。如果選擇該方案,需要單獨(dú)安裝APR庫(kù)。 | ||
2)Tomcat 支持的應(yīng)用層協(xié)議 :
應(yīng)用層協(xié)議 | 描述 | ||
---|---|---|---|
HTTP/1.1 | 這是大部分Web應(yīng)用采用的訪問(wèn)協(xié)議。 | ||
AJP | 用于和Web服務(wù)器集成(如Apache),以實(shí)現(xiàn)對(duì)靜態(tài)資源的優(yōu)化以及集群部署,當(dāng)前支持AJP/1.3。 | ||
HTTP/2 | HTTP 2.0大幅度的提升了Web性能。下一代HTTP協(xié)議 , 自8.5以及9.0版本之后支持。 | ||
3)協(xié)議分層 :
應(yīng)用層 | 傳輸層 | ||
---|---|---|---|
HTTP | NIO | ||
AJP | NIO2 | ||
HTTP2 | APR | ||
Processor | Endpoint | ||
4)在 8.0 之前 , Tomcat 默認(rèn)采用的I/O方式為 BIO , 之后改為 NIO。 無(wú)論 NIO、NIO2 還是 APR, 在性能方面均優(yōu)于以往的BIO。 如果采用APR, 甚至可以達(dá)到 Apache HTTP Server 的影響性能。
5)Tomcat 為了實(shí)現(xiàn)支持多種I/O模型和應(yīng)用層協(xié)議,一個(gè)容器可能對(duì)接多個(gè)連接器,就好比一個(gè)房間有多個(gè)門。但是單獨(dú)的連接器或者容器都不能對(duì)外提供服務(wù),需要把它們組裝起來(lái)才能工作,組裝后這個(gè)整體叫作Service組件。這里請(qǐng)你注意,Service本身沒(méi)有做什么重要的事情,只是在連接器和容器外面多包了一層,把它們組裝在一起。Tomcat 內(nèi)可能有多個(gè) Service,這樣的設(shè)計(jì)也是出于靈活性的考慮。通過(guò)在Tomcat中配置多個(gè) Service,可以實(shí)現(xiàn)通過(guò)不同的端口號(hào)來(lái)訪問(wèn)同一臺(tái)機(jī)器上部署的不同應(yīng)用。
四、 Tomcat專題 - Tomcat架構(gòu) - Coyote連接器組件
1、連接器組件:連接器中的各個(gè)組件的作用如下:
2、 EndPoint
1) EndPoint : Coyote 通信端點(diǎn),即通信監(jiān)聽的接口,是具體Socket接收和發(fā)送處理器,是對(duì)傳輸層的抽象,因此EndPoint用來(lái)實(shí)現(xiàn)TCP/IP協(xié)議的。
2) Tomcat 并沒(méi)有 EndPoint 接口,而是提供了一個(gè)抽象類 AbstractEndpoint ,里面定義了兩個(gè)內(nèi)部類:Acceptor 和 SocketProcessor。Acceptor 用于監(jiān)聽Socket連接請(qǐng)求。SocketProcessor 用于處理接收到的Socket請(qǐng)求,它實(shí)現(xiàn) Runnable 接口,在Run方法里調(diào)用協(xié)議處理組件 Processor 進(jìn)行處理。為了提高處理能力,SocketProcessor 被提交到線程池來(lái)執(zhí)行。而這個(gè)線程池叫作執(zhí)行器(Executor),我在后面的專欄會(huì)詳細(xì)介紹 Tomcat 如何擴(kuò)展原生的 Java 線程池。
3、Processor
Processor : Coyote 協(xié)議處理接口 ,如果說(shuō) EndPoint 是用來(lái)實(shí)現(xiàn) TCP/IP 協(xié)議的,那么 Processor 用來(lái)實(shí)現(xiàn)HTTP協(xié)議,Processor 接收來(lái)自 EndPoint 的 Socket,讀取字節(jié)流解析成 Tomcat Request 和 Response對(duì)象,并通過(guò) Adapter 將其提交到容器處理,Processor是對(duì)應(yīng)用層協(xié)議的抽象。
4、 ProtocolHandler
ProtocolHandler: Coyote 協(xié)議接口, 通過(guò)Endpoint 和 Processor , 實(shí)現(xiàn)針對(duì)具體協(xié)議的處理能力。Tomcat 按照協(xié)議和I/O 提供了6個(gè)實(shí)現(xiàn)類 : AjpNioProtocol , AjpAprProtocol, AjpNio2Protocol , Http11NioProtocol ,Http11Nio2Protocol ,Http11AprProtocol。我們?cè)谂渲胻omcat/conf/server.xml 時(shí) , 至少要指定具體的 ProtocolHandler , 當(dāng)然也可以指定協(xié)議名稱 , 如 : HTTP/1.1 ,如果安裝了APR,那么將使用Http11AprProtocol , 否則使用 Http11NioProtocol 。
5、 Adapter
由于協(xié)議不同,客戶端發(fā)過(guò)來(lái)的請(qǐng)求信息也不盡相同,Tomcat定義了自己的 Request 類來(lái)“存放”這些請(qǐng)求信息。ProtocolHandler 接口負(fù)責(zé)解析請(qǐng)求并生成 Tomcat Request 類。但是這個(gè) Request 對(duì)象不是標(biāo)準(zhǔn)的 ServletRequest,也就意味著,不能用 Tomcat Request 作為參數(shù)來(lái)調(diào)用容器。Tomcat設(shè)計(jì)者的解決方案是引入 CoyoteAdapter,這是適配器模式的經(jīng)典運(yùn)用,連接器調(diào)用 CoyoteAdapter 的 Sevice 方法,傳入的是 Tomcat Request 對(duì)象,CoyoteAdapter 負(fù)責(zé)將 Tomcat Request 轉(zhuǎn)成 ServletRequest,再調(diào)用容器的 Service方法。
五、 Tomcat專題 - Tomcat架構(gòu) - Catalina容器結(jié)構(gòu)
1、容器 - Catalina
-
Tomcat 是一個(gè)由一系列可配置的組件構(gòu)成的 Web 容器,而 Catalina 是 Tomcat 的 servlet 容器。
-
Catalina 是 Servlet 容器實(shí)現(xiàn),包含了之前講到的所有的容器組件,以及后續(xù)章節(jié)涉及到的安全、會(huì)話、集群、管理等 Servlet 容器架構(gòu)的各個(gè)方面。它通過(guò)松耦合的方式集成 Coyote,以完成按照請(qǐng)求協(xié)議進(jìn)行數(shù)據(jù)讀寫。同時(shí),它還包括我們的啟動(dòng)入口、Shell程序等。
2、Catalina 地位:Tomcat 的模塊分層結(jié)構(gòu)圖, 如下:
Tomcat 本質(zhì)上就是一款 Servlet 容器, 因此Catalina 才是 Tomcat 的核心 , 其他模塊都是為 Catalina 提供支撐的。 比如 : 通過(guò) Coyote 模塊提供鏈接通信,Jasper 模塊提供JSP引擎,Naming 提供 JNDI 服務(wù),Juli 提供日志服務(wù)。
3、Catalina 結(jié)構(gòu) :Catalina 的主要組件結(jié)構(gòu)如下:
Catalina 負(fù)責(zé)管理 Server,而 Server 表示著整個(gè)服務(wù)器。Server 下面有多個(gè)服務(wù) Service,每個(gè)服務(wù)都包含著多個(gè)連接器組件 Connector(Coyote 實(shí)現(xiàn))和一個(gè)容器組件 Container。在 Tomcat 啟動(dòng)的時(shí)候,會(huì)初始化一個(gè) Catalina 的實(shí)例。
4、Catalina 各個(gè)組件的職責(zé):
組件 | 職責(zé) | ||
---|---|---|---|
Catalina | 負(fù)責(zé)解析Tomcat的配置文件 , 以此來(lái)創(chuàng)建服務(wù)器Server組件,并根據(jù)命令來(lái)對(duì)其進(jìn)行管理 | ||
Server | 服務(wù)器表示整個(gè)Catalina Servlet容器以及其它組件,負(fù)責(zé)組裝并啟動(dòng)Servlet引擎,Tomcat連接器。Server通過(guò)實(shí)現(xiàn)Lifecycle接口,提供了一種優(yōu)雅的啟動(dòng)和關(guān)閉整個(gè)系統(tǒng)的方式 | ||
Service | 服務(wù)是Server內(nèi)部的組件,一個(gè)Server包含多個(gè)Service。它將若干個(gè)Connector組件綁定到一個(gè)Container(Engine)上 | ||
Connector | 連接器,處理與客戶端的通信,它負(fù)責(zé)接收客戶請(qǐng)求,然后轉(zhuǎn)給相關(guān)的容器處理,最后向客戶返回響應(yīng)結(jié)果 | ||
Container | 容器,負(fù)責(zé)處理用戶的servlet請(qǐng)求,并返回對(duì)象給web用戶的模塊 | ||
5、Container 結(jié)構(gòu)
Tomcat設(shè)計(jì)了4種容器,分別是 Engine、Host、Context 和 Wrapper。這4種容器不是平行關(guān)系,而是父子關(guān)系。Tomcat 通過(guò)一種分層的架構(gòu),使得Servlet容器具有很好的靈活性。
6、各個(gè)組件的含義 :
容器 | 描述 | ||
---|---|---|---|
Engine | 表示整個(gè)Catalina的Servlet引擎,用來(lái)管理多個(gè)虛擬站點(diǎn),一個(gè)Service最多只能有一個(gè)Engine,但是一個(gè)引擎可包含多個(gè)Host | ||
Host | 代表一個(gè)虛擬主機(jī),或者說(shuō)一個(gè)站點(diǎn),可以給Tomcat配置多個(gè)虛擬主機(jī)地址,而一個(gè)虛擬主機(jī)下可包含多個(gè)Context | ||
Context | 表示一個(gè)Web應(yīng)用程序, 一個(gè)Web應(yīng)用可包含多個(gè)Wrapper | ||
Wrapper | 表示一個(gè)Servlet,Wrapper 作為容器中的最底層,不能包含子容器 | ||
7、 也可以再通過(guò) Tomcat 的 server.xml 配置文件來(lái)加深對(duì) Tomcat 容器的理解。Tomcat 采用了組件化的設(shè)計(jì),它的構(gòu)成組件都是可配置的,其中最外層的是 Server,其他組件按照一定的格式要求配置在這個(gè)頂層容器中。
<Server<Service><Connector/><Connector/><Engine><Host><Context></Context></Host><Engine></Service>
</Server>
8、Tomcat 是怎么管理這些容器的呢?
這些容器具有父子關(guān)系,形成一個(gè)樹形結(jié)構(gòu),你可能馬上就想到了設(shè)計(jì)模式中的組合模式。沒(méi)錯(cuò),Tomcat 就是用組合模式來(lái)管理這些容器的。具體實(shí)現(xiàn)方法是,所有容器組件都實(shí)現(xiàn)了 Container 接口,因此組合模式可以使得用戶對(duì)單容器對(duì)象和組合容器對(duì)象的使用具有一致性。這里單容器對(duì)象指的是最底層的 Wrapper,組合容器對(duì)象指的是上面的 Context、Host 或 者Engine。
9、Container 接口中提供了以下方法(截圖中知識(shí)一部分方法) :
-
在上面的接口看到了getParent、SetParent、addChild和removeChild等方法。
-
Container 接口擴(kuò)展了 LifeCycle 接口,LifeCycle 接口用來(lái)統(tǒng)一管理各組件的生命周期,后面我也用專門的篇幅去詳細(xì)介紹。
上一節(jié)關(guān)聯(lián)鏈接請(qǐng)點(diǎn)擊
# 利刃出鞘_Tomcat 核心原理解析(一)