生活随笔
收集整理的這篇文章主要介紹了
Tomat6架构探讨(二续)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Tomat6架構探討(續) 原文地址:http://carllgc.blog.ccidnet.com/blog-htm-do-showone-uid-4092-type-blog-itemid-283322.html?
Tomat源碼學習(二) ? 下面,我們重點針對Catalina 子模塊,熟悉Tomcat的幾個關鍵組件。 ? (1) ???服務器 (Server) ?? 在 Tomcat 中,服務器代表整個 J2EE 容器,所有的服務及服務上下文均包含在服務器內。我們打開 Tomcat 源代碼,可以看到 org.apache.catalina.Server 這個接口,其中比較重要的方法有 initialize( 負責 Tomcat 啟動前的初始化工作 ) ,還有一些服務 (Services) 管理方法,比如 removeService() 、 addService() 、 findService() 之類的方法。 ? 在 Tomcat 運行時,我們永遠只有一個 Server 實例,這不由讓我們聯想到單例模式 (Singleton Pattern) 。不錯,在 Tomcat 中, Server 的實例化工作正是由一個叫 ServerFactory 工廠類完成的,這個工廠類實現了單例設計模式。 ? 比較有意思的是,這個工廠類的產品創建方法名為 getServer() 而不是標準的 createServer() 方法,并且沒有加 synchronized 或 synchronized(this) 保護,這是為什么呢?我們知道,在應用單例模式時,需要注意的一個關鍵點就是多線程的調用問題,如果我們的工廠類在創建單例對象時,這個工廠類有可能被多個線程并發調用的話,那么最好給這個工廠方法加上 synchronized 以避免產生兩個不同的產品類實例。如果您想避免 synchronized 的鎖機制造成的性能損失,請使用雙重檢查機制 (double-checked locking) 。所以,如果考慮多線程,這個工廠類的 getServer() 方法應該寫成:(紅色代碼是作者另加上的,源代碼中沒有)。 ? /**? * Return the singleton <code>Server</code> instance for this JVM.? */? public static Server getServer() {? if( server==null ){ ?synchronized (ServerFactory.class) {? if(server==null){ ?? server=new StandardServer();? }? }? }? return (server);? } ? 為什么 Tomcat 在實現時沒有加上面的紅色代碼呢?這是因為, Tomcat 啟動時創建 Server 對象,不可能出現多線程情況,所以就免掉了雙重檢查。如果我們確信沒有多線程調用我們的單例工廠類,我們也可以這樣做。 ? 另外,如果您對 ServerFactory 進行調試,您會發現一個非常有趣的現象,這個工廠先執行的不是 create 方法 ( 此處為 getServer 方法 ) ,而是 setServer 方法。這意味著這個工廠方法其實并不生產實際產品,實際產品是從別處產生,然后通過 setServer 方法注冊到這個 Factory 。當下次有客戶請求產品時,這個工廠方法只是簡單的把現成的單例產品傳給客戶。所以這個類其實只需一個單例類足矣,根本沒有必要使用工廠模式,所以 Tomcat 的開發者也覺得不好意思使用標準的工廠方法 createProduct ,殺雞焉用宰牛刀,對嗎? ? 在 Tomcat6.0 中,服務器 (Server) 接口的實現類只有一個,那就是 org.apache.catalina.core. ?StandardServer 類。這是一個標準的服務器實現類,這個類不但實現了 Server 接口,而且還實現了 Lifecycle 和 MBeanRegistration 接口, Lifecycle 主要提供了服務器的生命周期管理功能,比如說啟動、停止等方法,而 MBeanRegistration 接口是為了將 server 注冊到 MBean 服務器,以便在 Tomat 運行時,我們能通過 JMX 來管理服務器。 ? 從 Tomcat5.0 開始, Tomcat 的開發人員在 JMX 管理上著實下了一番功夫,爭取做到讓 Tomcat 具有 JBoss 那樣非常強大的管理功能。 ? (2) ???服務 (Service) ?在上述的標準服務器 (StanderServer.java) 實現代碼中,我們可以看到其中有一個 services 的數組,這個數組就是用來存儲服務 (Service) 的。所以,我們可以這樣理解,一個服務器可能有一至多個服務組成。所謂服務,就是包含一至多個連接器的組件,能夠對用戶請求作出響應的組件。打開 org.apache.catalina.Service.java 的源代碼,我們可以看到其中含有一個連接器數組 (Connector[]) ,這表明一個 Service 有可能包含一個到多個連接器。但所有這些連接器都屬于一個引擎 (Engine 或 Container) 。在 Tomcat6 中, org.apache.catalina.Service 接口由 org.apache.catalina.core. ?StandardService 類來實現的。 ? (3) ???引擎 (Engine) ?對一個具體的服務 (service) 來說,引擎是一個用戶請求的處理管道,這個管道很特別,因為它只處理 Servlet 請求,在 Tomcat 中,引擎其實就是指 Servlet 引擎。引擎從這些連接器那里接收到 Servlet 請求,然后處理它們,并將響應的結果傳回到適當的連接器,從而將響應發送到客戶端。簡單地說,引擎的功能就是如何處理用戶的 Servlet 請求。 ? org.apache.catalina.Engine 這個接口繼承自 org.apache.catalina.Container ,說明引擎是一種特殊的 Container ,是一種專門用來處理 servlet 請求的容器。 ? (4) ???主機 (Host) ?對 Tomcat 服務器來說,主機是 Tomcats 所在機器的網絡名 ( 域名 ) 。一個引擎可能包含多個主機,主機支持網絡別名。例如,用戶通過配置 config.xml 里面的主機 (Host) 元素,讓 www.abc.com 和 abc.com? 指向同一臺 Tomcat 應用服務器。 ? (5) ???連接器 (Connector) ?在 Tomcat 中,連接器負責和客戶端進行請求響應的交流。 Tomcat 中有兩種連接器 (Coyote 和 JK 連接器 ) , Coyote 連接器實現了 Http1.1 協議,我們可以將它理解為 Tomcat 的 Web 服務器部分。 JK 連接器負責處理來自第三方 Web 服務器的請求,并將請求結果發送給第三方 Web 服務器。針對 Apache Httpd Web 服務器, JK 連接器實現了 AJP 協議。 ? 在Tomcat6.0 中,實現 Coyote 連接器的類是 org.apache.catalina.connector.Connector 。 ? (6) ???上下文 (Context)? 上下文代表某一具體的 Web 應用,一個主機可包含多個 Web 應用,所以可有多個 Web 應用上下文,不同的上下文可用不同路徑來表示。上下文里含有一些關于該 Web 應用的一些具體信息,比如歡迎頁面的文件名, web.xml 文件的位置等等信息。 ? 上下文在 Tomcat 的源碼中對應 org.apache.catalina.Context 接口,其具體實現為 org.apache.catalina.core.StandardContext 。 ? 至此為止,我們熟悉了 Tomcat 架構中一些重要組件。下面我們用 UML 類圖 (Class Diagram) 來總結一下。 ? 在上面的類圖中,我們先撇開Tomcat 組件不談,首先給我們印象最深刻的一點是:針對接口編程,而非針對具體實現編程 (Program to interface, not implementation) 。人家老外這點確實值得我們學習。上面的類圖中,共有 7 個類,其余均為接口,這些類無一例外地調用了接口,而非具體的實現類。 ServerFactory 調用了 Server 接口,而非 StandServer 的實現類; Connector 類調用了 Service 接口和 Container 接口,而沒有調用它們的實現類; StandardService 類調用了 Container 接口和 Server 接口,也同樣沒有調用它們的實現類。所以我們在編程時,也要貫徹這條原則。 ? 在 <<Head First Design Patterns>> 一書里,作者舉了個非常生動的例子,請看下面三段代碼: ? a) ???代碼片段一 ? Dog d=new Dog();? d.bark();? b) ???代碼片段二 ? Animal animal=new Dog();? animal.makeSound(); ?c) ???代碼片段三 ? Animal animal = getAnimal();? animal.makeSound();? 作者詳細解釋了上面第三段代碼為什么是最好的,而第二段又為什么比第一段好的道理。東扯西拉這么多,現在我們切入正題。 ? 從上面的類圖中,我們可以非常清晰地理解 Tomcat 的總體架構: ? a) ???Server( 服務器 ) 是 Tomcat 構成的頂級構成元素,所有一切均包含在 Server 中, Server 的實現類 StandardServer 可以包含一個到多個 Services ; ? b) ???次頂級元素 Service 的實現類為 StandardService 調用了容器 (Container) 接口,其實是調用了 Servlet Engine( 引擎 ) ,而且 StandardService 類中也指明了該 Service 歸屬的 Server ; ? c) ???接下來次級的構成元素就是容器 (Container) ,主機 (Host) 、上下文 (Context) 和引擎 (Engine) 均繼承自 Container 接口,所以它們都是容器。但是,它們是有父子關系的,在主機 (Host) 、上下文 (Context) 和引擎 (Engine) 這三類容器中,引擎是頂級容器,直接包含是主機容器,而主機容器又包含上下文容器,所以引擎、主機和上下文從大小上來說又構成父子關系,雖然它們都繼承自 Container 接口。 ? d) ???連接器 (Connector) 沒有接口 ( 這可是違反了面向接口編程的原則喲! ) ,它直接實現了 Http1.1 協議。連接器將 Service 和 Container 連接起來,首先它需要注冊到一個 Service ,它的作用就是把來自客戶端的請求轉發到 Container( 容器 ) ,這就是它為什么稱作連接器的原因。 ? 下面我們來小結一下, Tomcat 的架構從功能的角度,可以分成 5 個子模塊,它們分別是 Connector 子模塊, Jsper 子模塊, Servlet 子模塊, Catalina 子模塊和 Resource 子模塊,每個子模塊負責一定的功能;從組件的角度,我們可以看到 Tomcat 中至少有 7 個關鍵組件,它們 Server 組件、 Service 組件、 Container 組件、 Connector 組件及繼承自 Container 組件的 Host 組件、 Engine 組件和 Container 組件,從 UML Class Diagram 中,我們可以非常明確地理解它們的包容關系。到此為止,希望我們能對 Tomcat 的架構有一個比較清晰的認識。 ?
轉載于:https://www.cnblogs.com/ToDoToTry/archive/2009/06/23/1509426.html
《新程序員》:云原生和全面數字化實踐 50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔 為你收集整理的Tomat6架构探讨(二续) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。