Tomcat架構(gòu)簡(jiǎn)析

Tomcat服務(wù)器作為目前比較流行的一種服務(wù)器容器已經(jīng)被廣泛用于后臺(tái)服務(wù)器的搭建姆吭、后臺(tái)集成框架的嵌入(如SpringBoot)冷溃,不同于Apache油昂、Nginx本身(注意是本身震贵,其實(shí)可以搭配后臺(tái)腳本實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè))僅僅支持靜態(tài)網(wǎng)頁(yè)擎宝,由于Tomcat其實(shí)是一種Servlet規(guī)范的實(shí)現(xiàn),而Servlet又支持JSP涡上,所以Tomcat實(shí)際上是完美支持動(dòng)態(tài)頁(yè)面的渲染的趾断。了解Tomcat的工作原理,有助于了解實(shí)際的后臺(tái)服務(wù)器是采用什么策略邏輯來(lái)實(shí)現(xiàn)的吩愧。網(wǎng)上有好多文章談及模塊組成芋酌、源碼解讀,但就我個(gè)人而言并不是很好理解耻警,所以參考了songxinjianqwe的開(kāi)源代碼手寫(xiě)簡(jiǎn)化版Web服務(wù)器隔嫡、劉光瑞大佬的書(shū)Tomcat架構(gòu)解析的第二章談一下個(gè)人的理解甸怕!其中songxinjianqwe的開(kāi)源代碼使用簡(jiǎn)明的邏輯簡(jiǎn)化實(shí)現(xiàn)了tomcat的一些基礎(chǔ)性的設(shè)計(jì)思想甘穿,劉光瑞的書(shū)籍從宏觀上由淺入深解釋了Tomcat的各個(gè)模塊是如何形成的。這里梢杭,我先講框架温兼,然后再分別結(jié)合songxinjianqwe的開(kāi)源代碼和Tomcat的原生代碼,較基礎(chǔ)的談一下Tomcat的設(shè)計(jì)思想武契。由于Tomcat的代碼復(fù)雜度很高募判,以我現(xiàn)在的水平基本很難理解更深的層次,而且個(gè)人認(rèn)為我現(xiàn)在的階段也不適合研究過(guò)深咒唆!

好了届垫,如果你已經(jīng)學(xué)習(xí)了基礎(chǔ)的Java多線程、Java網(wǎng)絡(luò)編程全释,讓你設(shè)計(jì)一個(gè)Http服務(wù)器你會(huì)怎么做装处?
1、初始化一個(gè)serversocket
2浸船、監(jiān)聽(tīng)客戶端連接妄迁,并通過(guò)accept創(chuàng)建客戶端socket
3、解析socket流李命,并構(gòu)造響應(yīng)數(shù)據(jù)
于是你的結(jié)構(gòu)圖是這樣的:


圖一

這是最簡(jiǎn)單的模型登淘,在這個(gè)模型里所有的Socket創(chuàng)建、連接封字、流操作都在一個(gè)模塊里黔州,但是Tomcat實(shí)際上為了多協(xié)議(不僅僅是Http耍鬓,還包括AJP等),所以為了使特定協(xié)議與Server解耦合流妻,Tomcat的設(shè)計(jì)者把連接和流操作分離開(kāi)來(lái)界斜,并讓Server分別持有連接、流操作合冀,于是結(jié)構(gòu)圖變成了這樣:


圖二

其中一個(gè)啟動(dòng)中的Server就是一個(gè)Tomcat應(yīng)用程序?qū)嵗鬓保粋€(gè)Server可以有多個(gè)Connector以管理多個(gè)連接協(xié)議,所以也可以持有不同的對(duì)應(yīng)的Engine來(lái)進(jìn)行流處理君躺。但是這里有個(gè)問(wèn)題就是峭判,N個(gè)Connector是如何對(duì)應(yīng)到M個(gè)Engine處理器以實(shí)現(xiàn)特定的連接交給特定的流處理器來(lái)執(zhí)行任務(wù)呢?為了解決這個(gè)問(wèn)題棕叫,Tomcat設(shè)計(jì)了Service模塊林螃,并變成了下面的結(jié)構(gòu)圖模型:


圖三

其中一個(gè)Service模塊維護(hù)多個(gè)Connector形成Connector集合并對(duì)應(yīng)一個(gè)Engine,而一個(gè)Server可以有多個(gè)Service俺泣!至此疗认,一個(gè)Tomcat基礎(chǔ)模型就構(gòu)建完成了,后續(xù)所有的功能模塊伏钠、線程設(shè)計(jì)均基于這個(gè)模型構(gòu)建横漏!我們首先要看的是Engine模塊,在流處理中依然有很多問(wèn)題要解決熟掂!第一個(gè)問(wèn)題缎浇,如果我這臺(tái)主機(jī)提供多個(gè)域名服務(wù),這時(shí)我們?cè)L問(wèn)不同的域名其實(shí)就得交由不同的應(yīng)用邏輯來(lái)處理赴肚,但是如果Engine只有一個(gè)(我們當(dāng)然可以創(chuàng)建多個(gè)Service進(jìn)而實(shí)現(xiàn)多個(gè)Engine素跺,最簡(jiǎn)單的方法就是再啟動(dòng)一個(gè)Tomcat),那么就必須在請(qǐng)求到達(dá)Engine后執(zhí)行分配邏輯誉券,來(lái)處理不同的域名下的服務(wù)指厌,Tomcat設(shè)計(jì)了虛擬主機(jī)的模塊來(lái)執(zhí)行這個(gè)功能,關(guān)于虛擬主機(jī)是這樣的一個(gè)概念:

在一臺(tái)Tomcat服務(wù)器中可以同時(shí)管理多個(gè)站點(diǎn)踊跟,即可以將多個(gè)站點(diǎn)配置在同一臺(tái)Tomcat服務(wù)器上踩验,而對(duì)于用戶(瀏覽器)而言,是不知道具體哪些網(wǎng)站是布置在同一臺(tái)Tomcat(服務(wù)器)之上的琴锭,對(duì)于用戶(瀏覽器)而言晰甚,每個(gè)站點(diǎn)都像是運(yùn)行在各自獨(dú)立的服務(wù)器上。此時(shí)每個(gè)網(wǎng)站就是運(yùn)行在同一臺(tái)這是服務(wù)器中各自對(duì)應(yīng)的虛擬主機(jī)上决帖。此時(shí)厕九,簡(jiǎn)單的理解,每個(gè)網(wǎng)站就可以認(rèn)為是一個(gè)虛擬主機(jī)地回。

添加了虛擬主機(jī)的模塊扁远,Tomcat于是就變成了下面的結(jié)構(gòu)模型:


圖四

當(dāng)請(qǐng)求過(guò)來(lái)的時(shí)候俊鱼,會(huì)通過(guò)解析當(dāng)前請(qǐng)求的域名來(lái)處理不同Hosts的數(shù)據(jù)流,所以一個(gè)Engine可以管理多個(gè)Hosts畅买!第二個(gè)問(wèn)題并闲,我們一直強(qiáng)調(diào)“流處理”,其實(shí)流處理就是根據(jù)當(dāng)前上下文的所有變量來(lái)實(shí)現(xiàn)Web應(yīng)用的功能邏輯罷了谷羞,如socket帝火、session、cookie等等湃缎,這些都是在一個(gè)流程處理中的所有有用變量或者對(duì)象犀填,而且這些對(duì)象會(huì)在不同類之間相互調(diào)用,那么如何保證這些變量或者對(duì)象可以靈活的獲取和構(gòu)造并保證一致性嗓违,Tomcat于是設(shè)計(jì)了context組件九巡,于是,就有了下面的模型:


圖五

這里的context其實(shí)就是ServletContext蹂季,實(shí)際上一個(gè)ServletContex就是代表了一個(gè)Web應(yīng)用冕广!所以一個(gè)Host下顯然可以有不同的Web應(yīng)用,即一個(gè)Host可以擁有多個(gè)context偿洁!因?yàn)檫@里我們談及了Servlet撒汉,上文也說(shuō)過(guò)Tomcat其實(shí)就是Servlet的規(guī)范實(shí)現(xiàn),所以一個(gè)Web應(yīng)用自然可以包含多個(gè)Servlet父能,Tomcat中定義為Wrapper神凑,于是就有了下面的模型圖:


圖六

Servlet的加載時(shí)通過(guò)反射的形式加載的,因?yàn)楫?dāng)我們創(chuàng)建Http服務(wù)器的時(shí)候何吝,我們所有的Servlet都是繼承HttpServlet,這樣當(dāng)讀取web.xml文件的時(shí)候就可以按照類似下面的代碼構(gòu)建我們創(chuàng)建的Servlet:

HttpServlet httpServlet  = (HttpServlet) Class.forName(“自定義Servlet的包路徑”).newInstance();

至此,關(guān)于Engine部分的內(nèi)容基本構(gòu)造完成鹃唯,但是Tomcat設(shè)計(jì)時(shí)為了統(tǒng)一管理右側(cè)的這些組件爱榕,實(shí)際把他們抽象成了一個(gè)被稱為container的組件,使得四個(gè)組件都繼承這個(gè)container坡慌,也就是我們說(shuō)的容器概念黔酥,然后統(tǒng)一管理各個(gè)組件的聲明周期!于是的Tomcat模型可以擴(kuò)充成這樣:


圖七

這里變成虛線洪橘,是為了體現(xiàn)各個(gè)組件實(shí)際上是由父類Container容器實(shí)現(xiàn)的“弱依賴”關(guān)系跪者,把原先的實(shí)現(xiàn)改為了虛線!至此我們看到一個(gè)較為完整的組件關(guān)系圖熄求,于是你們見(jiàn)到最多的關(guān)于Tomcat的結(jié)構(gòu)圖就是下面一幅:


圖八

這個(gè)架構(gòu)圖展示了上述Tomcat的核心組件渣玲,并表示出了各個(gè)組件間的組合關(guān)系:一個(gè)Server包含多個(gè)Service,一個(gè)Service包含多個(gè)Connector形成的一個(gè)集合弟晚,并對(duì)應(yīng)一個(gè)Container組件忘衍!

接下來(lái)逾苫,我們?cè)撎接慍onnector組件的實(shí)現(xiàn)細(xì)節(jié)!

我們提到Connector組件可以支持不同的協(xié)議枚钓,默認(rèn)是Http和AJP铅搓,實(shí)際上Connector還支持不同的I/O模型:如BIO、NIO搀捷、APR等等星掰,所以如何針對(duì)不同類型的連接方式來(lái)建立客戶端的通信,Tomcat設(shè)計(jì)了被稱為協(xié)議處理器的上層組件:ProtocolHandler嫩舟,如ProtocolHandler包含又包含兩個(gè)組件蹋偏,一個(gè)是抽象的AbstractEndpoint,用于實(shí)現(xiàn)不同的協(xié)議至壤、I/O模型威始。NioEndpoint指代非阻塞式SocketIO,另外還包含Processer組件用于實(shí)際的對(duì)應(yīng)容器的邏輯處理像街;于是就出現(xiàn)了類似Http11NioProtocol這樣的實(shí)現(xiàn)來(lái)處理支持Http1.1和NIO的連接方式黎棠,這樣我們的模型圖就變成了這樣:


圖九

這里面我們忽略一個(gè)上述文章中重要的一個(gè)組件功能:Service。這個(gè)組件如文章所述是建立Connector和Container(我們前文說(shuō)的是Engine镰绎,但是注意自從建立了Container組件脓斩,實(shí)際上Engine等四個(gè)組件被統(tǒng)稱為Container組件的子組件)的重要橋梁,所以實(shí)際上談?wù)揅onnector就必須談?wù)摰木褪荢ervice是如何實(shí)現(xiàn)兩者的映射關(guān)系的畴栖!當(dāng)Processor讀取請(qǐng)求信息后需要按照請(qǐng)求的信息映射到相應(yīng)的容器來(lái)處理随静,這里的映射信息是由Service的Maper和MaperListener來(lái)實(shí)現(xiàn)的,這里使用了觀察者模式來(lái)監(jiān)聽(tīng)客戶端的連接并注冊(cè)到Maper中吗讶,后續(xù)只需要根據(jù)Maper維護(hù)的映射信息即可找到對(duì)應(yīng)的容器燎猛。實(shí)際上為了實(shí)現(xiàn)Connector和Service的解耦運(yùn)用了適配器模式,所以Processor的一個(gè)默認(rèn)適配器實(shí)現(xiàn)被稱為CoyoteAdapter照皆;我們的模型圖變成了下面的結(jié)構(gòu):


圖十

但是Tomcat整合的考慮更多:既然可以由Container來(lái)統(tǒng)一表示這4個(gè)組件重绷,那么圖中所有的組件其實(shí)都包含啟動(dòng)膜毁、停止等各個(gè)生命周期,為了高效的管理個(gè)組件的運(yùn)行瘟滨,我們有必要把所有的組件在抽象成一個(gè)更通用的組件來(lái)進(jìn)行統(tǒng)一的管理,這里Tomcat設(shè)計(jì)了Lifecycle組件杂瘸,于是實(shí)際的Tomcat變成了下面的模型結(jié)構(gòu)圖:


圖十一

至此倒淫,一個(gè)基本的Tomcat模型就創(chuàng)造出來(lái)了胧沫!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末占业,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纯赎,更是在濱河造成了極大的恐慌谦疾,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件念恍,死亡現(xiàn)場(chǎng)離奇詭異晚顷,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)该默,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)栓袖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人裹刮,你說(shuō)我怎么就攤上這事≡穑” “怎么了违霞?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵葛家,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我癞谒,道長(zhǎng)刃榨,這世上最難降的妖魔是什么枢希? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任桌吃,我火速辦了婚禮苞轿,結(jié)果婚禮上逗物,老公的妹妹穿的比我還像新娘瑟俭。我一直安慰自己,他們只是感情好失暴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布微饥。 她就那樣靜靜地躺著,像睡著了一般矩肩。 火紅的嫁衣襯著肌膚如雪肃续。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天建炫,我揣著相機(jī)與錄音疼蛾,去河邊找鬼。 笑死察郁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的稳捆。 我是一名探鬼主播麦轰,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼款侵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了新锈?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤娜氏,失蹤者是張志新(化名)和其女友劉穎墩新,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體抖棘,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡切省,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了般渡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芙盘。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡儒老,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出驮樊,到底是詐尸還是另有隱情,我是刑警寧澤挖腰,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布猴仑,位于F島的核電站肥哎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏篡诽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望薄疚。 院中可真熱鬧赊琳,春花似錦砰碴、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)啃憎。三九已至,卻和暖如春辛萍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悯许。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工辉阶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人启上。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓冈在,卻偏偏與公主長(zhǎng)得像按摘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子炫贤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容