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