在實踐過程中,從WebSphere中實現一個EJB的容器以及從WebLogic中實現一個JMS幾乎都是不可能的,然而來自Apache基金會的servlet容器Tomcat至少在理論上是可能做到的。
請注意,這里所說的“接口”也包含抽象類。規范的API可能會提供一個實現的模板,其中包括定義了一些抽象的基本類型的操作來供服務提供者去實現。
而服務提供者應提供這些接口和抽象類的具體實現。例如,在Tomcat中HttpSession接口被以org.apache.catalina.session.StandardSession的形式實現。
下面讓我們來看看Tomcat容器的整體結構:
本文的目的是覆蓋這張圖中所涉及的主要請求處理組件。而上圖中的一些高級主題如集群和安全則不是在本文討論的范圍之內。
本圖中,Service, Host, Context以及Wrapper實例之后的符號“+”表示這些對象能存在一個或多個。例如一個Service可能只有一個Engine,但是一個Engine可以包含一個或多個Host;另外,圖中旋轉的圓圈代表請求處理器的線程池。
?
1、組件分類
Tomcat架構采用類似俄羅斯嵌套娃娃(譯注:一層套一層)的設計方式。換句話說,就是一個容器包含另一個容器,而這個被包含的容器實體反過來再包含別的實體。
而在Tomcat中,“容器”是對任何包含有其他組件的組件的通稱,如Server、Service、Engine、Host以及Context都稱為容器。 其中Server和Service組件比較特殊些,被設計為頂級元素,代表Tomcat運行實例。而Tomcat其他所有的組件都屬于這些頂級元素。其中Engine、Host以及Contex都被官方稱為容器并依賴處理傳入請求和生成適當數據響應的相關組件。
而被嵌套的組件可以作為子元素來嵌入頂級元素或其他容器之中來配置這些組件的工作方式。這其中,嵌套組件包括代表可重用的工作單元的Valve組件、代表Valve鏈的Pipeline組件以及幫助特定容器建立容器管理安全的Realm組件。
此外,嵌套組件中還包括用來強制servlet中的類使用指定的規范來加載類的加載器;為每個web應用提供session管理的管理器;代表web應用中靜態資源以及提供機制來訪問這些資源的資源管理組件;以及在容器的生命周期內允許在重要的點插入自定義處理程序的監聽器組件,例如當某個組件啟動或停止時就可以使用監聽器。
值得注意的是,并不是所有的前臺組件都可以被嵌套在每個容器中。
這里還有最后一個主要組件,那就是連接器(Connector);它代表一個連接點,通過這個連接點外部客戶端可以(比如網頁瀏覽器)可以連接至Tomcat容器。
在我們去學習這些組件之前,讓我們快速看下這些組件的大體結構:
請注意,上圖只展示了每個容器的關鍵屬性。
啟動Tomcat時,它運行的Java虛擬機(JVM)實例中包含一個服務器頂級元素,該元素代表了一個完整Tomcat服務器。一個Tomcat服務器通常只包含一個Service對象,這個對象是一種包含一個或多個連接器(Connector,如HTTP、HTTPS連接器)的結構化元素,正是這些Connector通過一個Catalina的Servlet引擎來處理傳入的請求。
引擎(Engine)表示Tomcat中處理請求的核心代碼,并且它還支持在其下定義多個虛擬主機(Host)。虛擬主機允許Tomcat引擎在將配置在一臺機器上的多個域名(如www.my-site.com、www.your-site.com)分割開來互不干擾。
反過來,每個虛擬主機又可以支持多個web應用部署在它下邊,這就是我們所熟知的上下文對象(Context)。上下文(Context)是使用由Servlet規范中指定的Web應用程序格式表示,不論是壓縮過的war包形式的文件還是未壓縮的目錄形式。此外,上下文一般是在web.xml文件中配置,并且該配置是根據servlet規范定義的。
從上下問角度看,在上下文中又可以部署多個servlet,并且每個servlet都會被一個包裝組件所包含。
至此,我們以上所說的Server、Service、Connector、Engine、Host、Context元素都會通過server.xml配置文件在tomcat實例中被使用。
?
2、架構的好處
這種架構有一些很實用的功能。它不僅便于組件的生命周期管理(每個組件管理生命周期并通知其子節點),而且便于在Tcomat啟動時根據從配置文件中讀取的配置文件來動態組裝出Tomcat服務器實例。尤其是server.xml在啟動時就會被解析,其內容正是用來實例化和配置被定義的元素,并隨后組裝到正在運行的Tomcat實例中。
server.xml文件只會被讀取一次,對server.xml的修改只有在Tomcat重啟后才會起作用。
同時這種架構簡化配置,允許子容器繼承父容器的配置。例如Realm定義了一個可驗證權限的數據存儲,并且可以授權用戶通過web應用來訪問受保護資源。為了便于配置,針對引擎定義的Realm適用于它所有的host和context配置。同時,某一個特定的子元素如context也可以通過繼承父類的realm來實現自定義realm。
?
3、頂級組件
Server和Service容器組件存在的目的是盡可能的方便結構化。Server表示正在運行的Tomcat實例,可包含一個或多個Service子容器;其中每個Service代表一組請求處理組件。
Server
Server代表完整的Tomcat實例在Java虛擬集中是單例,主要是用來管理容器下各個Serivce組件的生命周期。
下圖描述了Server組件的關鍵方面。如圖所示,Server實例是通過server.xml配置文件來配置的;其根元素<Server>所代表的正是Tomcat實例,默認實現為org.apache.catalina.core.StandardServer。但是,你也可以通過<Server>標簽的class屬性來自定義服務器實現。
服務器可重要的一方面就是它打開了8005端口(默認端口)來監聽關閉服務命令(默認情況下命令為SHUTDOWN)。當收到shutdown命令后,服務器會優雅的關閉自己。同時出于安全考慮,發起關閉請求的連接必須來自同一臺機器上的同一個運行中的Tomcat實例。
此外,Server還提供了一個Java命名服務和JNDI服務,可以通過這兩個服務可以使用名稱來注冊專用對象(如數據源配置)。在運行期,單個組件(如Servlet)可以使用對象名稱來通過服務器的JNDI綁定服務來查找需要的對象相關信息。
雖然JNDI實現并不是Servlet容器的功能,但是它屬于JavaEE規范一部分,并且可以為Servlet從應用服務器或者servlet容器中獲取所需要的信息提供服務。
雖然在一個JVM中通常只有一個服務器實例,但是完全可以在同一臺物理機器中運行多個服務器實例,每個實例對應一個JVM實例;這種做法將運行在一個JVM中的應用中的錯誤與其他JVM中應用的錯誤隔離開來互不影響,這也簡化了維護使得JVM的重啟與其他獨立開來。這是一個共享主機環境的機制(另一種是虛擬主機機制,很快我們將會看到),這種機制下需要將運行在同一物理主機下的多個web應用隔離開來。
Service
Server代表Tomcat實例本身,Service則代表Tomcat中一組請求處理的組件。
Server可以包含一個或多個Service,但每個Service則將一組Connector組件和Engine關聯了起來。
客戶端請求首先到達連接器(connector),連接器在再將這些請求輪流傳入引擎中處理,而Engine也是Tomcat中請求處理的關鍵組件。上圖中展示了HTTP連接器、HTTPS連接以及AJP組件。
一般很少會修改這個元素,而且默認的Service實例通常就足夠使用了。
值得注意的是上圖中可能有多個Service實例。如圖所示,一個Service集中了一些連接器,每個連接器監控一個指定的IP及端口并通過指定的協議做出響應。所以,一個關于多個服務的使用示例就是當你希望通過IP地址或者端口號來區分不同服務(包括這些服務中所包含的engine、host、web應用)時。
例如,當需要配置防火墻來為用戶開放某一個服務而該主機上托管的其他服務仍然只是對內部用戶可見,這將確保外部用戶無法訪問內部應用程序,因為對應訪問會被防火墻攔截。
因此,Service僅僅是一個分組結構,它并不包含任何其他的附加功能。
4、連接器(Connector)
Connector是客戶端連接到Tomcat容器的服務點它為引擎提供協議服務來將引擎與客戶端各種協議隔離開來,如HTTP、HTTPS、AJP協議。
Tomcat有兩種可配的工作模式--獨立模式或在同一web服務器中共享模式。
在獨立模式下,Tomcat會配置HTTP和HTTPS連接器,這可以使Tomcat看起來更像完整的web服務器以處理靜態請求內容同時還委托Catalina引擎來處理動態內容。
發布時,Tomcat為這種運作模式提供了3種可能實現,即HTTP、HTTP1.1以及HTTPS。
Tomcat中最常見的連接器為標準連接器,也就是通過java標準I/O實現的Coyote連接器。
你也許希望使用一些技術實現,這其中就包括使用Java1.4中引入的非阻塞特性NIO,另一方面可能是通過APR充分利用本地代碼來優化特定的操作系統。
值得注意的是,Connector和Engine不僅運行在同一個JVM中,而且還運行在同一個Tomcat服務實例中。
在共享模式中,Tomcat扮演著對web服務器如Apache httpd和微軟的IIS支撐的角色。這里web服務器充當客戶端通過Apache模塊或者通過dll格式ISAPI模塊來和Tomcat通信。當該模塊判定一個請求需要傳入Tomcat處理時,它將使用AJP協議來與Tomcat通信,該協議為二進制協議,在web服務器和Tomcat通信時比基于文本的Http協議更高效。
在Tomcat端,通過AJP連接器來接收wen服務器的請求,并將請求解釋為Catalina引擎可處理的格式。
這種模式下Tomcat作為來自web服務器的單獨進程運行在自身獨立的JVM中。
不論在哪種模式中,Connector的基本屬性都是它所需要監聽的IP地址及端口號,以及所支持的協議。還有一個關鍵屬性就是并發處理傳入請求的最大線程數。一旦所有的處理線程都忙,那么傳入的請求都將被忽略,直到有線程空閑為止。
默認情況下,連接器會監聽指定物理機器上的所有IP(address屬性默認值為0.0.0.0);但也可以配置為只監聽某一個IP,這將限制它只接收指定ip的連接請求。
任意一個連接器接收到的請求都會被傳入單一的服務引擎中,而這個引擎,就是眾所周知的catalina,它負責處理請求并生成響應結果。
引擎將生成的結果返回給連接器,連接器再通過指定的協議將結果回傳至客戶端。
?
未完待續......
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
