俗話說截型,站在巨人的肩膀上看世界,一般學(xué)習(xí)的時候也是先總覽一下整體轿秧,然后逐個部分個個擊破,最后形成思路咨堤,了解具體細(xì)節(jié)菇篡,Tomcat的結(jié)構(gòu)很復(fù)雜,但是 Tomcat 非常的模塊化一喘,找到了 Tomcat最核心的模塊驱还,問題才可以游刃而解嗜暴,了解了Tomcat的整體架構(gòu)對以后深入了解Tomcat來說至關(guān)重要!
一议蟆、Tomcat頂層架構(gòu)
先上一張Tomcat的頂層結(jié)構(gòu)圖(圖A)闷沥,如下:
Tomcat中最頂層的容器是Server,代表著整個服務(wù)器咐容,從上圖中可以看出舆逃,一個Server可以包含至少一個Service,用于具體提供服務(wù)戳粒。
Service主要包含兩個部分:Connector和Container路狮。從上圖中可以看出 Tomcat 的心臟就是這兩個組件,他們的作用如下:
1蔚约、Connector用于處理連接相關(guān)的事情奄妨,并提供Socket與Request和Response相關(guān)的轉(zhuǎn)化;
2、Container用于封裝和管理Servlet苹祟,以及具體處理Request請求砸抛;
一個Tomcat中只有一個Server,一個Server可以包含多個Service树枫,一個Service只有一個Container直焙,但是可以有多個Connectors,這是因為一個服務(wù)可以有多個連接团赏,如同時提供Http和Https鏈接箕般,也可以提供向相同協(xié)議不同端口的連接,示意圖如下(Engine、Host舔清、Context下邊會說到):
多個 Connector 和一個 Container 就形成了一個 Service丝里,有了 Service 就可以對外提供服務(wù)了,但是 Service 還要一個生存的環(huán)境体谒,必須要有人能夠給她生命杯聚、掌握其生死大權(quán),那就非 Server 莫屬了抒痒!所以整個 Tomcat 的生命周期由 Server 控制幌绍。
另外,上述的包含關(guān)系或者說是父子關(guān)系故响,都可以在tomcat的conf目錄下的server.xml配置文件中看出傀广,下圖是刪除了注釋內(nèi)容之后的一個完整的server.xml配置文件(Tomcat版本為8.0)
詳細(xì)的配置文件文件內(nèi)容可以到Tomcat官網(wǎng)查看:http://tomcat.apache.org/tomcat-8.0-doc/index.html
上邊的配置文件,還可以通過下邊的一張結(jié)構(gòu)圖更清楚的理解:
Server標(biāo)簽設(shè)置的端口號為8005彩届,shutdown=”SHUTDOWN” 伪冰,表示在8005端口監(jiān)聽“SHUTDOWN”命令,如果接收到了就會關(guān)閉Tomcat樟蠕。一個Server有一個Service贮聂,當(dāng)然還可以進(jìn)行配置靠柑,一個Service有多個,Service左邊的內(nèi)容都屬于Container的吓懈,Service下邊是Connector歼冰。
二、Tomcat頂層架構(gòu)小結(jié):
(1)Tomcat中只有一個Server耻警,一個Server可以有多個Service隔嫡,一個Service可以有多個Connector和一個Container;
(2) Server掌管著整個Tomcat的生死大權(quán)榕栏;
(4)Service 是對外提供服務(wù)的畔勤;
(5)Connector用于接受請求并將請求封裝成Request和Response來具體處理;
(6)Container用于封裝和管理Servlet扒磁,以及具體處理request請求庆揪;
知道了整個Tomcat頂層的分層架構(gòu)和各個組件之間的關(guān)系以及作用,對于絕大多數(shù)的開發(fā)人員來說Server和Service對我們來說確實很遠(yuǎn)妨托,而我們開發(fā)中絕大部分進(jìn)行配置的內(nèi)容是屬于Connector和Container的缸榛,所以接下來介紹一下Connector和Container。
三兰伤、Connector和Container的微妙關(guān)系
由上述內(nèi)容我們大致可以知道一個請求發(fā)送到Tomcat之后内颗,首先經(jīng)過Service然后會交給我們的Connector,Connector用于接收請求并將接收的請求封裝為Request和Response來具體處理敦腔,Request和Response封裝完之后再交由Container進(jìn)行處理均澳,Container處理完請求之后再返回給Connector,最后在由Connector通過Socket將處理的結(jié)果返回給客戶端符衔,這樣整個請求的就處理完了找前!
Connector最底層使用的是Socket來進(jìn)行連接的,Request和Response是按照HTTP協(xié)議來封裝的判族,所以Connector同時需要實現(xiàn)TCP/IP協(xié)議和HTTP協(xié)議躺盛!
Tomcat既然處理請求,那么肯定需要先接收到這個請求形帮,接收請求這個東西我們首先就需要看一下Connector槽惫!
四、Connector架構(gòu)分析
Connector用于接受請求并將請求封裝成Request和Response辩撑,然后交給Container進(jìn)行處理界斜,Container處理完之后在交給Connector返回給客戶端。
因此合冀,我們可以把Connector分為四個方面進(jìn)行理解:
(1)Connector如何接受請求的锄蹂?
(2)如何將請求封裝成Request和Response的?
(3)封裝完之后的Request和Response如何交給Container進(jìn)行處理的水慨?
(4)Container處理完之后如何交給Connector并返回給客戶端的得糜?
首先看一下Connector的結(jié)構(gòu)圖(圖B),如下所示:
Connector就是使用ProtocolHandler來處理請求的晰洒,不同的ProtocolHandler代表不同的連接類型朝抖,比如:Http11Protocol使用的是普通Socket來連接的,Http11NioProtocol使用的是NioSocket來連接的谍珊。
其中ProtocolHandler由包含了三個部件:Endpoint治宣、Processor、Adapter砌滞。
(1)Endpoint用來處理底層Socket的網(wǎng)絡(luò)連接侮邀,Processor用于將Endpoint接收到的Socket封裝成Request,Adapter用于將Request交給Container進(jìn)行具體的處理贝润。
(2)Endpoint由于是處理底層的Socket網(wǎng)絡(luò)連接绊茧,因此Endpoint是用來實現(xiàn)TCP/IP協(xié)議的,而Processor用來實現(xiàn)HTTP協(xié)議的打掘,Adapter將請求適配到Servlet容器進(jìn)行具體的處理华畏。
(3)Endpoint的抽象實現(xiàn)AbstractEndpoint里面定義的Acceptor和AsyncTimeout兩個內(nèi)部類和一個Handler接口。Acceptor用于監(jiān)聽請求尊蚁,AsyncTimeout用于檢查異步Request的超時亡笑,Handler用于處理接收到的Socket,在內(nèi)部調(diào)用Processor進(jìn)行處理横朋。
至此仑乌,我們應(yīng)該很輕松的回答(1)(2)(3)的問題了,但是(4)還是不知道琴锭,那么我們就來看一下Container是如何進(jìn)行處理的以及處理完之后是如何將處理完的結(jié)果返回給Connector的晰甚?
五、Container架構(gòu)分析
Container用于封裝和管理Servlet祠够,以及具體處理Request請求压汪,在Connector內(nèi)部包含了4個子容器,結(jié)構(gòu)圖如下(圖C):
4個子容器的作用分別是:
(1)Engine:引擎古瓤,用來管理多個站點(diǎn)止剖,一個Service最多只能有一個Engine;
(2)Host:代表一個站點(diǎn)落君,也可以叫虛擬主機(jī)穿香,通過配置Host就可以添加站點(diǎn);
(3)Context:代表一個應(yīng)用程序绎速,對應(yīng)著平時開發(fā)的一套程序皮获,或者一個WEB-INF目錄以及下面的web.xml文件;
(4)Wrapper:每一Wrapper封裝著一個Servlet纹冤;
下面找一個Tomcat的文件目錄對照一下洒宝,如下圖所示:
Context和Host的區(qū)別是Context表示一個應(yīng)用购公,我們的Tomcat中默認(rèn)的配置下webapps下的每一個文件夾目錄都是一個Context,其中ROOT目錄中存放著主應(yīng)用雁歌,其他目錄存放著子應(yīng)用宏浩,而整個webapps就是一個Host站點(diǎn)。
我們訪問應(yīng)用Context的時候靠瞎,如果是ROOT下的則直接使用域名就可以訪問比庄,例如:www.ledouit.com,如果是Host(webapps)下的其他應(yīng)用,則可以使用www.ledouit.com/docs進(jìn)行訪問乏盐,當(dāng)然默認(rèn)指定的根應(yīng)用(ROOT)是可以進(jìn)行設(shè)定的佳窑,只不過Host站點(diǎn)下默認(rèn)的主營用是ROOT目錄下的。
看到這里我們知道Container是什么父能,但是還是不知道Container是如何進(jìn)行處理的以及處理完之后是如何將處理完的結(jié)果返回給Connector的神凑?別急!下邊就開始探討一下Container是如何進(jìn)行處理的法竞!
六耙厚、Container如何處理請求的
Container處理請求是使用Pipeline-Valve管道來處理的!(Valve是閥門之意)
Pipeline-Valve是責(zé)任鏈模式岔霸,責(zé)任鏈模式是指在一個請求處理的過程中有很多處理者依次對請求進(jìn)行處理薛躬,每個處理者負(fù)責(zé)做自己相應(yīng)的處理,處理完之后將處理后的請求返回呆细,再讓下一個處理著繼續(xù)處理型宝。
但是!Pipeline-Valve使用的責(zé)任鏈模式和普通的責(zé)任鏈模式有些不同絮爷!區(qū)別主要有以下兩點(diǎn):
(1)每個Pipeline都有特定的Valve趴酣,而且是在管道的最后一個執(zhí)行,這個Valve叫做BaseValve坑夯,BaseValve是不可刪除的岖寞;
(2)在上層容器的管道的BaseValve中會調(diào)用下層容器的管道。
我們知道Container包含四個子容器柜蜈,而這四個子容器對應(yīng)的BaseValve分別在:StandardEngineValve仗谆、StandardHostValve、StandardContextValve淑履、StandardWrapperValve隶垮。
Pipeline的處理流程圖如下(圖D):
(1)Connector在接收到請求后會首先調(diào)用最頂層容器的Pipeline來處理,這里的最頂層容器的Pipeline就是EnginePipeline(Engine的管道)秘噪;
(2)在Engine的管道中依次會執(zhí)行EngineValve1狸吞、EngineValve2等等,最后會執(zhí)行StandardEngineValve,在StandardEngineValve中會調(diào)用Host管道蹋偏,然后再依次執(zhí)行Host的HostValve1便斥、HostValve2等,最后在執(zhí)行StandardHostValve威始,然后再依次調(diào)用Context的管道和Wrapper的管道椭住,最后執(zhí)行到StandardWrapperValve。
(3)當(dāng)執(zhí)行到StandardWrapperValve的時候字逗,會在StandardWrapperValve中創(chuàng)建FilterChain,并調(diào)用其doFilter方法來處理請求宅广,這個FilterChain包含著我們配置的與請求相匹配的Filter和Servlet葫掉,其doFilter方法會依次調(diào)用所有的Filter的doFilter方法和Servlet的service方法,這樣請求就得到了處理跟狱!
(4)當(dāng)所有的Pipeline-Valve都執(zhí)行完之后俭厚,并且處理完了具體的請求,這個時候就可以將返回的結(jié)果交給Connector了驶臊,Connector在通過Socket的方式將結(jié)果返回給客戶端挪挤。
總結(jié)
至此,我們已經(jīng)對Tomcat的整體架構(gòu)有了大致的了解关翎,從圖A扛门、B、C纵寝、D可以看出來每一個組件的基本要素和作用论寨。我們在腦海里應(yīng)該有一個大概的輪廓了!如果你面試的時候爽茴,讓你簡單的聊一下Tomcat葬凳,上面的內(nèi)容你能脫口而出嗎?當(dāng)你能夠脫口而出的時候室奏,這位面試官一定會對你刮目相看的火焰!
原文:https://blog.csdn.net/xlgen157387/article/details/79006434