tomcat整體架構
1.背景
Tomcat作為JavaWeb領域的Web容器,目前在我們淘寶也使用的也非常廣泛,現在基本上所有線上業務系統都是部署在Tomcat上。為了對平時開發的Web系統有更深入的理解以及出於好奇心對我們寫的Web系統是如何跑在Tomcat上的,於是仔細研究了下Tomcat的原始碼。大家都知道Servlet規範是Java領域中為服務端程式設計制定的規範,對於我們開發者只是關注了Servlet規範中提供的程式設計元件(ServletContextListener,Filer,Servlet) 等 ,但是規範中還有一些我們經常使用的介面(ServletContext,ServletRequest,ServletResponse,FilterChain)等都是由Tomcat去實現的,並且我們開發者實現的程式設計元件只是被Tomcat去回撥而已。所以看Tomcat原始碼實現也有助於我們更好的理解Servlet規範及系統如何在容器中執行(一些開源的MVC框架如Struts2,Webx,SpringMVC本質無非就是這個)
2.Tomcat體系結構
仔細檢視下圖(網路上描述Tomcat架構比較清晰的一張圖),不難發現其中的Connecotr元件以及與Container元件是Tomcat的核心。一個Server可以有多個Service,而一個Service可以包含了多個Connector元件和一個Engine容器元件,一個Engine可以由多個虛擬主機Host組成,每一個Host下面又可以由多個Web應用Context構成,每一個的Context下面可以包含多個Wrapper(Servlet的包裝器)組成。
Tomcat將Engine,Host,Context,Wrapper統一抽象成Container。一個抽象的Container模組可以包含各種服務。例如,Manager管理器(Session管理),Pipeline管道( 維護管道閥門Value )等。Lifecycle介面統一定義了容器的生命週期,通過事件機制實現各個容器間的內部通訊。而容器的核心介面Container的抽象實現中定義了一個Pipeline,一個Manager,一個Realm以及ClassLoader統一了具體容器的實現規範。聯結器(Connector)元件的主要任務是為其所接收到的每一個請求(可以是HTTP協議,也可以AJP協議),委託給具體相關協議的解析類ProtocolHandler,構造出Request 物件和Response 物件。然後將這兩個物件傳送給容器(Container)進行處理。容器(Container)元件收到來自聯結器(Connector)的Request 和Response物件後,負責呼叫Filter,最後呼叫Servlet的service 方法(進入我們開發的Web系統中)。

1.Server元件:Server是最頂級的元件,代表Tomcat的執行例項;包含Listener元件用以監聽生命週期中的各種事件;包含GlobalNamingResources元件用以整合JNDI;包含Service元件用以提供服務。
2.Service元件:Service是服務的抽象,代表請求從接受到處理的所有元件的集合;Server元件可以包含多個Service元件;包含Connector元件用以接收客戶端的資訊;包含Engine元件用以處理請求;包含Executor用以提供執行緒池執行任務。
3.Connector元件:接收客戶端連線並接收資訊報文,資訊報文經由它解析後送往容器中處理;包含Mapper元件對請求地址進行路由;包含CoyoteAdaptor元件用以將Connector元件和Engine等容器元件適配起來;包含Protocol元件用以接收客戶端連線、接收客戶端資訊報文、報文解析處理、對客戶端響應等整個過程。
4.Protocol元件:包含JioEndPoint元件,其中的Acceptor元件將啟動某個埠的監聽,將監聽到的請求放入執行緒池Executor元件,其中的Processor元件對HTTP協議解析並傳遞到Engine容器繼續處理;IO/">NIO模式下NioEndPoint多了一個Poller元件輪詢多個客戶端連線處理事件。
Engine元件:代表全域性Servlet引擎;每個Service元件只能包含一個Engine容器元件;包含Listener元件用以在生命週期中對Engine相關的事件進行監聽;包含AccessLog元件以記錄訪問日誌;包含Cluster元件以提供叢集功能,將需要共享的資料同步到叢集中的其他Tomcat例項中;包含Pipeline元件用以處理請求;包含Realm元件用以提供安全許可權功能。
5.Host元件:代表虛擬主機;一個Engine元件可以包含若干個Host容器元件;包含Listener元件用以在生命週期中對Host相關的事件進行監聽;包含AccessLog元件以記錄訪問日誌;包含Cluster元件以提供叢集功能,將需要共享的資料同步到叢集中的其他Tomcat例項中;包含Pipeline元件用以處理請求;包含Realm元件用以提供安全許可權功能。
6.Context元件:是Web應用的抽象,Web應用部署到Tomcat後執行時就會轉化成Context物件;包含了各種靜態資源、若干Servlet(Wrapper容器)以及各種其他動態資源;
包含Listener元件用以在生命週期中對Context相關的事件進行監聽;
包含AccessLog元件以記錄訪問日誌;
包含Pipeline元件用以處理請求;
包含Realm元件用以提供安全許可權功能;
包含Loader元件用以載入Web應用的資源,保證不同Web應用之間的資源隔離;
包含Manager元件用以管理Web容器的會話,包括維護會話的生成、更新和銷燬;
包含NamingResource元件將Tomcat配置檔案的server.xml和Web應用的context.xml資源和屬性對映到記憶體中;
7.Mapper元件用以作為路由對映Servlet。
8.Wrapper元件:對應的是Servlet;包含Web應用開發常用的Servlet元件;包含ServletPool元件用以存放Servlet物件,當Web應用的Servlet實現了SingleThreadModel介面時則會再Wrapper中產生一個Servlet物件池,執行緒執行時,需先從物件池中獲取到一個Servlet物件,ServletPool元件能保證Servlet物件的執行緒安全;包含Pipeline元件用以處理請求。
我們從功能的角度將Tomcat原始碼分成5個子模組,它們分別是:
- Jsper子模組:這個子模組負責jsp頁面的解析、jsp屬性的驗證,同時也負責將jsp頁面動態轉換為java程式碼並編譯成class檔案。在Tomcat原始碼中,凡是屬於org.apache.jasper包及其子包中的原始碼都屬於這個子模組;
- Servlet和Jsp規範的實現模組:這個子模組的原始碼屬於javax.servlet包及其子包,如我們非常熟悉的javax.servlet.Servlet介面、javax.servet.http.HttpServlet類及javax.servlet.jsp.HttpJspPage就位於這個子模組中;
- Catalina子模組:這個子模組包含了所有以org.apache.catalina開頭的java原始碼。該子模組的任務是規範了Tomcat的總體架構,定義了Server、Service、Host、Connector、Context、Session及Cluster等關鍵元件及這些元件的實現,這個子模組大量運用了Composite設計模式。同時也規範了Catalina的啟動及停止等事件的執行流程。從程式碼閱讀的角度看,這個子模組應該是我們閱讀和學習的重點。
- Connectors子模組:如果說上面三個子模組實現了Tomcat應用伺服器的話,那麼這個子模組就是Web伺服器的實現。所謂聯結器(Connector)就是一個連線客戶和應用伺服器的橋樑,它接收使用者的請求,並把使用者請求包裝成標準的Http請求(包含協議名稱,請求頭Head,請求方法是Get還是Post等等)。同時,這個子模組還按照標準的Http協議,負責給客戶端傳送響應頁面,比如在請求頁面未發現時,connector就會給客戶端瀏覽器傳送標準的Http 404錯誤響應頁面。
- Resource子模組:這個子模組包含一些資原始檔,如Server.xml及Web.xml配置檔案。嚴格說來,這個子模組不包含java原始碼,但是它還是Tomcat編譯執行所必需的。