全國(guó)咨詢(xún)/投訴熱線(xiàn):400-618-4000

首頁(yè)技術(shù)文章正文

一次請(qǐng)求的來(lái)龍去脈 - Tomcat架構(gòu)解析(二)

更新時(shí)間:2022-11-18 來(lái)源:黑馬程序員 瀏覽量:

  > 容器,簡(jiǎn)單理解就是用來(lái)裝東西的工具。在Tomcat里面,容器被設(shè)計(jì)用來(lái)裝載Servlet, 也就是我們平常寫(xiě)的普通的Servlet ,就會(huì)存放在容器里面。這也就是咱們平常念叨的Servlet容器,其實(shí)從廣義上理解,Servlet容器是指Tomcat,從狹義上理解,Servlet容器,只是Tomcat里面的一個(gè)組件而已。

      1.容器概述

  Tomcat采用分層結(jié)構(gòu)設(shè)計(jì)了4種容器,這4種容器分別是: Engine 、Host 、Context 、Wrap 。它們鈞繼承 Container 容器接口。這樣設(shè)計(jì)使得Tomcat在處理請(qǐng)求時(shí),分工更加明確,也使得容器具有很好的靈活性。

  

1668738242662_1.jpg

  其中從左到右: Engine 表示引擎,用來(lái)管理多個(gè)虛擬站點(diǎn),一個(gè)Service最多只能有一個(gè)Engine。 Host代表虛擬主機(jī),或者表示站點(diǎn)。其實(shí)就是我們配置出來(lái)的虛擬映射地址。Context表示一個(gè)Web應(yīng)用,Wrap 名為包裝,它其實(shí)就是內(nèi)部包裝著我們寫(xiě)的Servlet。

  為了方便大家理解,我們可以從Tomcat里面的server.xml中看出來(lái)一些端倪。

1668738254985_2.jpg

  這四個(gè)容器呈現(xiàn)的是一個(gè)父子包含關(guān)系:

1668738269382_3.jpg

  2. 定位Servlet

  > 在Tomcat里面使用Mapper 映射器來(lái)實(shí)現(xiàn)Servlet的定位工作。在最初啟動(dòng)項(xiàng)目的時(shí)候,Tomcat就開(kāi)始解析了項(xiàng)目的配置信息,然后使用Mapper來(lái)保存了具體的映射地址和Host、Context、Wrap的對(duì)應(yīng)關(guān)系。當(dāng)請(qǐng)求到來(lái)的時(shí)候,就會(huì)到Mapper里面去查找匹配的Wrap(Servlet),然后調(diào)用。當(dāng)我們?yōu)榱朔奖憷斫?,我們可以淺顯的認(rèn)為Mapper其實(shí)就是一個(gè)類(lèi)似Map鍵值對(duì)的容器。

  2.1 全局概覽

  比如: 下面的圖示,我們可以把瑞吉點(diǎn)餐項(xiàng)目的面向管理員后臺(tái)項(xiàng)目和面向用戶(hù)前端項(xiàng)目部署在同一個(gè)Tomcat上,為了隔離它們,我們通過(guò)配置虛擬域名,也就是兩個(gè)Host。而用戶(hù)系統(tǒng),訂單系統(tǒng),產(chǎn)品系統(tǒng),購(gòu)物車(chē)系統(tǒng)又都是可以獨(dú)立運(yùn)行的應(yīng)用,所以我們可以配備4個(gè)Context來(lái)對(duì)應(yīng)它們。最后一排的Wrap,其實(shí)就是各自系統(tǒng)中的Servlet了。

1668738294771_4.jpg

  2.2 請(qǐng)求到來(lái)

  > 此時(shí)用戶(hù)使用 http://user.reggie.com:8080/cart/delete 來(lái)訪(fǎng)問(wèn)。

  2.2.1 定位Service和Engine

  由于來(lái)訪(fǎng)的時(shí)候,使用的是8080端口,正好被Http連接器捕捉到。在Tomcat里面,Service里面包含著: 連接器和容器。找到了連接器,也就意味著找到了容器,這也就意味著Engine就確定了。

  2.2.2 定位Host

  Service和Engine確定了之后,就在Mapper中,通過(guò)路徑地址,找到響應(yīng)的Host容器。由于使用的是user.reggie.com 訪(fǎng)問(wèn),所以這就確定了是Host2這個(gè)容器。

  2.2.3 定位Context

  Host確定了之后,繼續(xù)在Mapper中查找。由于使用的/cart訪(fǎng)問(wèn),所以這就定位到了Context4這個(gè)應(yīng)用。

  2.2.4 定位Wrap

  Context確定了之后,后續(xù)也就能根據(jù)地址 /delete,輕而易舉的找到 Wrap6 這個(gè)容器。最后也就定位到了Servlet。

  2.3 請(qǐng)求傳遞

  > Tomcat 里面是如何把請(qǐng)求從最外層的容器Engine,一直往里傳遞到Wrap,然后執(zhí)行Servlet的調(diào)用的呢?

  >

  > 答案是使用 Pipeline-Valve 管道。

  >

  > Pipeline-Valve 是責(zé)任鏈模式,責(zé)任鏈模式是指在一個(gè)請(qǐng)求處理的過(guò)程中有很多處理者依次對(duì)請(qǐng)求進(jìn)行處理,每個(gè)處理者負(fù)責(zé)做自己相應(yīng)的處理,處理完之后將再調(diào)用下一個(gè)處理者繼續(xù)處理。

  下面通過(guò)一個(gè)張簡(jiǎn)單的草圖來(lái)描述:

  每一個(gè)容器都有一個(gè)Pipeline對(duì)象,中間的每一個(gè)圓圈,其實(shí)表示的是一個(gè)Valve,它表示處理點(diǎn)。在Pipeline里面維護(hù)這Valve的鏈表。只要執(zhí)行了第一個(gè)Pipeline的Valve,這個(gè)容器中的Pipeline就會(huì)被調(diào)用,直到最后末端的Basic的Valve,它負(fù)責(zé)去連接下一個(gè)子容器的第一個(gè)Valve處理點(diǎn)。這樣不斷的串聯(lián)起來(lái),最終就到達(dá)了Servlet。

1668738380702_5.jpg

  值得注意的是: 在Wrap的最后一個(gè)Basic的Valve的處理點(diǎn)里面,它會(huì)創(chuàng)建一個(gè)Filter過(guò)濾器鏈,然后在doFilter方法中最終調(diào)用Servlet的service方法。

  3. 總結(jié)

  本文主要給大家描述了Tomcat了里面的容器結(jié)構(gòu),以及請(qǐng)求到來(lái)的時(shí)候,是如何識(shí)別到底執(zhí)行了哪個(gè)Servlet。請(qǐng)求的鏈?zhǔn)秸{(diào)用是基于 Pipeline-Valve 責(zé)任鏈來(lái)完成的,這樣的設(shè)計(jì)使得系統(tǒng)具有良好的可擴(kuò)展性,如果需要擴(kuò)展容器本身的功能,只需要增加相應(yīng)的 Valve 即可。

分享到:
在線(xiàn)咨詢(xún) 我要報(bào)名
和我們?cè)诰€(xiàn)交談!