Tomcat詳解系列(2) – 理解Tomcat架構設計

Tomcat – 理解Tomcat架構設計

前文我們已經介紹了一個簡單的Servlet容器是如何設計出來,我們就可以開始正式學習Tomcat了,在學習開始,我們有必要站在高點去看看Tomcat的架構設計。@pdai

準備知識

一些準備知識點。

Tomcat和Catalina是什麼關係?

Tomcat的前身為Catalina,Catalina又是一個輕量級的Servlet容器

Tomcat的前身為Catalina,Catalina又是一個輕量級的Servlet容器。在美國,catalina是一個很美的小島。所以Tomcat作者的寓意可能是想把Tomcat設計成一個優雅美麗且輕量級的web服務器。Tomcat從4.x版本開始除了作為支持Servlet的容器外,額外加入了很多的功能,比如:jsp、el、naming等等,所以說Tomcat不僅僅是Catalina

什麼是Servlet?

所謂Servlet,其實就是Sun為了讓Java能實現動態可交互的網頁,從而進入Web編程領域而制定的一套標準!

在互聯網興起之初,當時的Sun公司(後面被Oracle收購)已然看到了這次機遇,於是設計出了Applet來對Web應用的支持。不過事實卻並不是預期那麼得好,Sun悲催地發現Applet並沒有給業界帶來多大的影響。經過反思,Sun就想既然機遇出現了,市場前景也非常不錯,總不能白白放棄了呀,怎麼辦呢?於是又投入精力去搞一套規範出來,這時Servlet誕生了!

一個Servlet主要做下面三件事情:

  • 創建並填充Request對象,包括:URI、參數、method、請求頭信息、請求體信息等
  • 創建Response對象
  • 執行業務邏輯,將結果通過Response的輸出流輸出到客戶端

Servlet沒有main方法,所以,如果要執行,則需要在一個容器裏面才能執行,這個容器就是為了支持Servlet的功能而存在,Tomcat其實就是一個Servlet容器的實現

Tomcat 總結架構

下圖應該是網上能找的最好的關於Tomcat的架構圖了, 我們來看下它的構成:

從組件的角度看

  • Server: 表示服務器,它提供了一種優雅的方式來啟動和停止整個系統,不必單獨啟停連接器和容器;它是Tomcat構成的頂級構成元素,所有一切均包含在Server中;

  • Service: 表示服務,Server可以運行多個服務。比如一個Tomcat裏面可運行訂單服務、支付服務、用戶服務等等;Server的實現類StandardServer可以包含一個到多個Services, Service的實現類為StandardService調用了容器(Container)接口,其實是調用了Servlet Engine(引擎),而且StandardService類中也指明了該Service歸屬的Server;

  • Container: 表示容器,可以看做Servlet容器;引擎(Engine)、主機(Host)、上下文(Context)和Wraper均繼承自Container接口,所以它們都是容器。

    • Engine — 引擎
    • Host — 主機
    • Context — 上下文
    • Wrapper — 包裝器
  • Connector: 表示連接器, 它將Service和Container連接起來,首先它需要註冊到一個Service,它的作用就是把來自客戶端的請求轉發到Container(容器),這就是它為什麼稱作連接器, 它支持的協議如下:

    • 支持AJP協議
    • 支持Http協議
    • 支持Https協議
  • Service內部還有各種支撐組件,下面簡單羅列一下這些組件

    • Manager — 管理器,用於管理會話Session
    • Logger — 日誌器,用於管理日誌
    • Loader — 加載器,和類加載有關,只會開放給Context所使用
    • Pipeline — 管道組件,配合Valve實現過濾器功能
    • Valve — 閥門組件,配合Pipeline實現過濾器功能
    • Realm — 認證授權組件

從web.xml配置和模塊對應角度

上述模塊的理解不是孤立的,它直接映射為Tomcat的web.xml配置,讓我們聯繫起來看

從一個完整請求的角度來看

通過一個完整的HTTP請求,我們還需要把它貫穿起來

假設來自客戶的請求為://localhost:8080/test/index.jsp 請求被發送到本機端口8080,被在那裡偵聽的Coyote HTTP/1.1 Connector,然後

  • Connector把該請求交給它所在的Service的Engine來處理,並等待Engine的回應
  • Engine獲得請求localhost:8080/test/index.jsp,匹配它所有虛擬主機Host
  • Engine匹配到名為localhost的Host(即使匹配不到也把請求交給該Host處理,因為該Host被定義為該Engine的默認主機)
  • localhost Host獲得請求/test/index.jsp,匹配它所擁有的所有Context
  • Host匹配到路徑為/test的Context(如果匹配不到就把該請求交給路徑名為””的Context去處理)
  • path=”/test”的Context獲得請求/index.jsp,在它的mapping table中尋找對應的servlet
  • Context匹配到URL PATTERN為*.jsp的servlet,對應於JspServlet類,構造HttpServletRequest對象和HttpServletResponse對象,作為參數調用JspServlet的doGet或doPost方法
  • Context把執行完了之後的HttpServletResponse對象返回給Host
  • Host把HttpServletResponse對象返回給Engine
  • Engine把HttpServletResponse對象返回給Connector
  • Connector把HttpServletResponse對象返回給客戶browser

從源碼的設計角度看

從功能的角度將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的啟動及停止等事件的執行流程。從代碼閱讀的角度看,這個子模塊應該是我們閱讀和學習的重點。

  • Connector模塊: 如果說上面三個子模塊實現了Tomcat應用服務器的話,那麼這個子模塊就是Web服務器的實現。所謂連接器(Connector)就是一個連接客戶和應用服務器的橋樑,它接收用戶的請求,並把用戶請求包裝成標準的Http請求(包含協議名稱,請求頭Head,請求方法是Get還是Post等等)。同時,這個子模塊還按照標準的Http協議,負責給客戶端發送響應頁面,比如在請求頁面未發現時,connector就會給客戶端瀏覽器發送標準的Http 404錯誤響應頁面。

  • Resource模塊: 這個子模塊包含一些資源文件,如Server.xml及Web.xml配置文件。嚴格說來,這個子模塊不包含java源代碼,但是它還是Tomcat編譯運行所必需的。

從後續深入理解的角度

我們看完上述組件結構後,後續應該重點從哪些角度深入理解Tomcat呢?

  • 基於組件的架構

我們知道組成Tomcat的是各種各樣的組件,每個組件各司其職,組件與組件之間有明確的職責劃分,同時組件與組件之間又通過一定的聯繫相互通信。Tomcat整體就是一個個組件的堆砌!

  • 基於JMX

我們在後續閱讀Tomcat源碼的時候,會發現代碼里充斥着大量的類似於下面的代碼。

Registry.getRegistry(null, null).invoke(mbeans, "init", false);
Registry.getRegistry(null, null).invoke(mbeans, "start", false);

而這實際上就是通過JMX來管理相應對象的代碼。這兒我們不會詳細講述什麼是JMX,我們只是簡單地說明一下JMX的概念,參考JMX百度百科。

JMX(Java Management Extensions,即Java管理擴展)是一個為應用程序、設備、系統等植入管理功能的框架。JMX可以跨越一系列異構操作系統平台、系統體系結構和網絡傳輸協議,靈活的開發無縫集成的系統、網絡和服務管理應用。

  • 基於生命周期

如果我們查閱各個組件的源代碼,會發現絕大多數組件實現了Lifecycle接口,這也就是我們所說的基於生命周期。生命周期的各個階段的觸發又是基於事件的方式。

更多文章

相關文章