來源:北大青鳥總部 2023年08月30日 09:10
作為一個web開發者,自打進入這一行,每天接觸最多的可能就是服務器了,每天最多的操作可能就是啟動服務器,關掉服務器,各種測試操作。
很多時候,對它是又愛又恨,愛的是它確實是我們做web開發必不可少的東西,而且很優秀;恨的是,每天都要經常啟動,停止;不厭其煩的操作。
雖然我們每天都在使用Tomcat服務器,大家就是知道這是一個很好用的服務器,但是我猜很多開發者肯能并不一定清楚的它的來歷,也未必對它的原理有過研究。
提到Tomcat,大家可能最先想到的就是一只可愛的小貓咪,但是你沒有想過,這個為什么一個服務器會和一致可愛的小貓咪聯系在一起呢,好像八竿子也打不著的親戚,所以,今天咱們就來了解下Tomcat的前世今生......

· Tomcat的由來
Tomcat 服務器是一個免費的開放源的Web應用服務器,屬于輕量級應用服務器,廣泛應用于web開發,深受廣大開發者喜愛,是目前比較流行的Web應用服務器。
Tomcat是Apache 軟件基金會(ApacheSoftwareFoundation)的一個核心項目,Tomcat最初是由Sun的軟件架構師詹姆斯·鄧肯·戴維森開發的,并由Sun貢獻給Apache軟件基金會。由Apache Sun和其他一些公司及個人共同開發而成。由于有了Sun的參與和支持,最新的Servlet和JSP規范總是能在Tomcat中得到體現。
但是人們不禁對這個Tomcat和小貓咪的關系感到好奇,Tomcat的這個單詞是“公貓/野貓”的意思,因為它的開發者姆斯·鄧肯·戴維森希望用一種能夠自己照顧自己的動物代表這個軟件,于是命名為tomcat,它的Logo兼吉祥物也被設計成了一只公貓形象。還有就是,具說姆斯·鄧肯·戴維森在擼代碼的時候,他養的小貓總是在他的鍵盤上跳來跳去,所有就多種因素在一起,就有了今天的Tomcat.
但其實,在Tomcat里還有另外一些有意思的故事,比如Tomcat中最核心的模塊Servlet,在它的作者開發這個模塊的時候,就給他起了聽上去都很美的名字Catalina,這個單詞的意思是“卡特琳娜”,沒錯,它就是一個連作者自己的都沒去過的美麗的小島,果然得不到的永遠在騷動~~~
好了,關于Tomcat的由來的故事基本就這么多吧,感覺還是跟很多軟件的故事類似,要么起個地名,要么起個動物名。

· Tomcat的原理
Tomcat 作為一個Http服務器 +Servlet容器,屏蔽了很多應用層協議和網絡通信細節,給我們的是標準的Request和 Response對象,當我們在使用SpringMVC之類的框架的時候,從來都不考慮一個請求的具體的實現細節,就是因為 Tomcat已經為我們做好了這些,我們只需要關注每個請求的具體業務邏輯。
說到這些實現細節,可是復雜了,我們先從整體整體架構上來看下Tomcat的總體結構。

從上圖中可以看出 Tomcat有很多組件,但是比較核心的是Connector和Container兩個組件,這兩個組件分別控制著Tomcat于外界的聯系,一個控制著Tomcat的生命周期。
Connector(連接器) :Tomcat 與外部世界的連接器,監聽固定端口接收外部請求,傳遞給 Container,并 將 Container 處理的結果返回給外部
Container(容器):Catalina,Servlet 容器,內部有多層容器組成,用于管理 Servlet 生命周期,調用 servlet 相關方法
Server(服務器):代表Tomcat本身,用來接收客戶端發請求數據并進行解析,啟動service并監聽端口等
Service(服務器):它負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收
Engine(引擎):表示可運行的Catalina的servlet引擎實例,負責請求 的處理。
Context(上下文容器):也可以看成Web應用。Context上下文代表 Servlet 的 Context,它具備了 Servlet 運行的基本環境,它表示Web應用程序本身
Host(虛擬主機):是web應用容器或者是Tomcat中所說的上下文虛擬主機
Wrapper(包裝器):表示一個單獨的servlet,負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收
· Tomcat的處理流程
說完了Tomcat的核心組件,我們再來看下Tomcat的處理流程,當一個請求過來之后,Tomcat是怎么處理的,我們上面介紹到的這些組件優勢怎么發揮作用的,我們先來看一張圖。

1、用戶點擊網頁內容,請求被發送到本機端口8080,被在那里監聽的Coyote HTTP/1.1 Connector獲得
2、Connector把該請求交給它所在的Service的Engine來處理,并等待Engine的響應
3、Engine獲得請求localhost/index.jsp,匹配所有的虛擬主機Host
4、Engine匹配到名為localhost的Host(即使匹配不到也把請求交給該Host處理,因為該Host被定義為該Engine的默認主機),名為localhost的Host獲得請求/index.jsp,匹配它所擁有的所有的Context。Host匹配到路徑為/的Context(如果匹配不到就把該請求交給路徑名為“ ”的Context去處理)
5、path=“/”的Context獲得請求/index.jsp,在它的mapping table中尋找出對應的Servlet。Context匹配到URL PATTERN為*.jsp的Servlet, 對應于JspServlet類
6、構造HttpServletRequest對象和HttpServletResponse對象,作為參數調用JspServlet的doGet()或doPost(),執行業務邏輯、數據存儲等程序
7、Context把執行完之后的HttpServletResponse對象返回給Host
8、Host把HttpServletResponse對象返回給Engine
9、Engine把HttpServletResponse對象返回Connector
10、Connector把HttpServletResponse對象返回給客戶Browser
最終將處理后的結果,渲染之后返回給瀏覽器,這樣一個請求就算完成啦!