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

pdai發表於2021-03-18

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請求,我們還需要把它貫穿起來

假設來自客戶的請求為: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介面,這也就是我們所說的基於生命週期。生命週期的各個階段的觸發又是基於事件的方式。

更多文章

相關文章

相關文章