核心部分
1. 定義
Tomcat 服務器是一個免費的開放源代碼的Web 應用服務器,Tomcat是Apache 軟件基金會(Apache Software Foundation)的Jakarta 項目中的一個核心項目,它早期的名稱為catalina,后來由Apache、Sun 和其他一些公司及個人共同開發而成,並更名為Tomcat。Tomcat 是一個小型的輕量級應用服務器,在中小型系統和並發訪問用戶不是很多的場合下被普遍使用,是開發和調試JSP 程序的首選,因為Tomcat 技術先進、性能穩定,成為目前比較流行的Web 應用服務器。Tomcat是應用(java)服務器,它只是一個servlet容器,是Apache的擴展,但它是獨立運行的。
最本質上講,tomcat為一個jsp/servlet容器
2. 組件
1. 頂級組件
Server:表示一個Tomcat實例 (單例的);Server代表整個catalina servlet容器;包含一個或多個service子容器。主要是用來管理容器下各個Serivce組件的生命周期。
Service:代表Tomcat中一組提供服務、處理請求的組件。是一個分組結構,包括多個Connector和一個Container。
2. 連接器
Connector是客戶端連接到Tomcat容器的服務點,它為引擎提供協議服務來將引擎與客戶端各種協議隔離開來,如HTTP、HTTPS、AJP協議。Connector的基本屬性都是它所需要監聽的IP地址及端口號,以及所支持的協議。還有一個關鍵屬性就是並發處理傳入請求的最大線程數。注意,Connector關鍵的有 連接器(HTTP HTTPS HTTP1.1 AJP SSL proxy) 運行模式(BIO NIO NIO2/AIO APR)多線程/線程池
3. 容器組件
Container是容器的父接口,用於封裝和管理Servlet,以及具體處理Request請求,該容器的設計用的是典型的責任鏈的設計模式,它由四個自容器組件構成,分別是Engine、Host、Context、Wrapper。這四個組件是負責關系,存在包含關系。只包含一個引擎。
Engine 引擎:表示可運行的Catalina的servlet引擎實例,並且包含了servlet容器的核心功能。在一個服務中只能有一個引擎。同時,作為一個真正的容器,Engine元素之下可以包含一個或多個虛擬主機。它主要功能是將傳入請求委托給適當的虛擬主機處理。如果根據名稱沒有找到可處理的虛擬主機,那么將根據默認的Host來判斷該由哪個虛擬主機處理。
Host 虛擬主機:作用就是運行多個應用,它負責安裝和展開這些應用,並且標識這個應用以便能夠區分它們。它的子容器通常是 Context。一個虛擬主機下都可以部署一個或者多個Web App,每個Web App對應於一個Context,當Host獲得一個請求時,將把該請求匹配到某個Context上,然后把該請求交給該Context來處理。主機組件類似於Apache中的虛擬主機,但在Tomcat中只支持基於FQDN(完全合格的主機名)的“虛擬主機”。Host主要用來解析web.xml。
Context上下文:代表 Servlet 的 Context,它具備了 Servlet 運行的基本環境,它表示Web應用程序本身。Context 最重要的功能就是管理它里面的 Servlet 實例,一個Context對應於一個Web Application,一個Web Application由一個或者多個Servlet實例組成。
Wrapper包裝器: 代表一個 Servlet,它負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收。Wrapper 是最底層的容器,它沒有子容器了,所以調用它的 addChild 將會報錯。
4. 嵌套組件
Valve閥門:類似於Servlet規范中定義的過濾器,用來攔截請求並在將其轉至目標之前進行某種處理操作。Valve可以定義在任何容器類的組件中。Valve常被用來記錄客戶端請求、客戶端IP地址和服務器等信息,這種處理技術通常被稱作請求轉儲(request dumping)。請求轉儲valve記錄請求客戶端請求數據包中的HTTP首部信息和cookie信息文件中,響應轉儲valve則記錄響應數據包首部信息和cookie信息至文件中。
Logger日志記錄器:用於記錄組件內部的狀態信息,可被用於除Context之外的任何容器中。日志記錄的功能可被繼承,因此,一個引擎級別的Logger將會記錄引擎內部所有組件相關的信息,除非某內部組件定義了自己的Logger組件。
Loader類加載器:負責加載、解釋Java類編譯后的字節碼。
Realm領域:用於用戶的認證和授權;在配置一個應用程序時,管理員可以為每個資源或資源組定義角色及權限,而這些訪問控制功能的生效需要通過Realm來實現。Realm的認證可以基於文本文件、數據庫表、LDAP服務等來實現。Realm的效用會遍及整個引擎或頂級容器,因此,一個容器內的所有應用程序將共享用戶資源。同時,Realm可以被其所在組件的子組件繼承,也可以被子組件中定義的Realm所覆蓋。
Excutor執行器:執行器組件允許您配置一個共享的線程池,以供您的連接器使用。從tomcat 6.0.11版本開始。
Listener監聽器:監聽已注冊組件的生命周期。
Manager會話管理器:用於實現http會話管理的功能,tomcat6種有5種會話管理的manager的實現(standardManager、persisentManager、DeltaManager、BackupManager、SimpleTcpReplicationManager)。會話讓使用無狀態HTTP協議的應用程序完成通信。會話表示客戶端和服務器之間的通信,會話功能是由javax.servlet.http.HttpSession 的實例實現的,該實例存儲在服務器上而且與一個唯一的標識符相關聯,客戶端在與服務器的每次交互中根據請求中的標識符找到它的會話。一個新的會話在客戶端請求后被創建,會話一直有效直到一段時間后客戶端連接超時,或者會話直接失效例如客戶退出訪問服務器。
Cluster集群:專用於配置Tomcat集群的元素,可用於Engine和Host容器中。
架構好處: 1. 便於組件生命周期的管理; 2. 簡化配置,允許子容器繼承父容器的配置。
Tomcat架構圖
1. 原圖
Tomca的心臟是兩個組件:Connector和Container(Engine,Host,Context,Wrapper)。一個Container可以選擇多個Connecter,多個Connector和一個Container就形成了一個Service。Service可以對外提供服務,而Server服務器控制整個Tomcat的生命周期。
2. 簡圖
Server、Service、Connector、Engine、Host、Context元素都會通過server.xml配置文件在tomcat實例中被使用。
server.xml文件只會被讀取一次,對server.xml的修改只有在Tomcat重啟后才會起作用。
架構好處: 1. 便於組件生命周期的管理; 2. 簡化配置,允許子容器繼承父容器的配置。
它不僅便於組件的生命周期管理(每個組件管理生命周期並通知其子節點),而且便於在Tcomat啟動時根據從配置文件中讀取的配置文件來動態組裝出Tomcat服務器實例。尤其是server.xml在啟動時就會被解析,其內容正是用來實例化和配置被定義的元素,並隨后組裝到正在運行的Tomcat實例中。
同時這種架構簡化配置,允許子容器繼承父容器的配置。例如Realm定義了一個可驗證權限的數據存儲,並且可以授權用戶通過web應用來訪問受保護資源。為了便於配置,針對引擎定義的Realm適用於它所有的host和context配置。同時,某一個特定的子元素如context也可以通過繼承父類的realm來實現自定義realm。
Tomcat組件
1. 頂級組件Server
服務器(server):表示一個正在JVM運行的Tomcat實例 (單例的);Server代表整個catalina servlet容器;包含一個或多個service子容器。
Server代表完整的Tomcat實例,在Java虛擬機中是單例,主要是用來管理容器下各個Serivce組件的生命周期。
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中啟動一個Tomcat實例,每個實例分屬於一個獨立的管理端口。);這種做法將運行在一個JVM中的應用中的錯誤與其他JVM中應用的錯誤隔離開來互不影響,這也簡化了維護使得JVM的重啟與其他獨立開來。這是一個共享主機環境的機制(另一種是虛擬主機機制,很快我們將會看到),這種機制下需要將運行在同一物理主機下的多個web應用隔離開來。
2. 頂級組件Service
Server代表Tomcat實例本身,Service則代表Tomcat中一組處理請求,提供服務的組件。包括多個Connector和一個Container。
Server可以包含一個或多個Service,但每個Service則將一組Connector組件和Engine關聯了起來。
客戶端請求首先到達連接器(connector),連接器在再將這些請求輪流傳入引擎中處理,而Engine也是Tomcat中請求處理的關鍵組件。上圖中展示了HTTP連接器、HTTPS連接以及AJP組件。
一個Service集中了一些連接器,每個連接器監控一個指定的IP及端口並通過指定的協議做出響應。
所以,一個關於多個服務的使用示例就是當你希望通過IP地址或者端口號來區分不同服務(包括這些服務中所包含的engine、host、web應用)時。例如,當需要配置防火牆來為用戶開放某一個服務而該主機上托管的其他服務仍然只是對內部用戶可見,這將確保外部用戶無法訪問內部應用程序,因為對應訪問會被防火牆攔截。因此,Service僅僅是一個分組結構,它並不包含任何其他的附加功能。
3. Connector
Connector是客戶端連接到Tomcat容器的服務點,它為引擎提供協議服務來將引擎與客戶端各種協議隔離開來,如HTTP、HTTPS、AJP協議。
Tomcat有兩種可配的工作模式--獨立模式或在同一web服務器中共享模式。
獨立模式:
一個Connecter將在某個指定的端口上偵聽客戶請求,接收瀏覽器的發過來的 tcp 連接請求,創建一個 Request 和 Response 對象分別用於和請求端交換數據,然后會產生一個線程來處理這個請求並把產生的 Request 和 Response 對象傳給處理Engine(Container中的一部分),從Engine出獲得響應並返回客戶。
在獨立模式下,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、Nginx和微軟的IIS支撐的角色。這里web服務器充當客戶端通過Apache模塊或者通過dll格式ISAPI模塊來和Tomcat通信。當該模塊判定一個請求需要傳入Tomcat處理時,它將使用AJP協議來與Tomcat通信,該協議為二進制協議,在web服務器和Tomcat通信時比基於文本的Http協議更高效。
在Tomcat端,通過AJP連接器來接收web服務器的請求,並將請求解釋為Catalina引擎可處理的格式。
這種模式下Tomcat作為來自web服務器的單獨進程運行在自身獨立的JVM中。
不論在哪種模式中,Connector的基本屬性都是它所需要監聽的IP地址及端口號,以及所支持的協議。還有一個關鍵屬性就是並發處理傳入請求的最大線程數。一旦所有的處理線程都忙,那么傳入的請求都將被忽略,直到有線程空閑為止。
默認情況下,連接器會監聽指定物理機器上的所有IP(address屬性默認值為0.0.0.0);但也可以配置為只監聽某一個IP,這將限制它只接收指定ip的連接請求。
任意一個連接器接收到的請求都會被傳入單一的服務引擎中,而這個引擎,就是眾所周知的catalina,它負責處理請求並生成響應結果。
引擎將生成的結果返回給連接器,連接器再通過指定的協議將結果回傳至客戶端。
注意,Connector關鍵的有 連接器(HTTP HTTPS HTTP1.1 AJP SSL proxy)
運行模式(BIO NIO NIO2/AIO APR)
多線程/線程池
看一下Connector的結構圖(圖B),如下所示:
Connector就是使用ProtocolHandler來處理請求的,不同的ProtocolHandler代表不同的連接類型,比如:Http11Protocol使用的是普通Socket來連接的,Http11NioProtocol使用的是NioSocket來連接的。
其中ProtocolHandler由包含了三個部件:Endpoint、Processor、Adapter。
(1)Endpoint用來處理底層Socket的網絡連接,Processor用於將Endpoint接收到的Socket封裝成Request,Adapter用於將Request交給Container進行具體的處理。
(2)Endpoint由於是處理底層的Socket網絡連接,因此Endpoint是用來實現TCP/IP協議的,而Processor用來實現HTTP協議的,Adapter將請求適配到Servlet容器進行具體的處理。
(3)Endpoint的抽象實現AbstractEndpoint里面定義的Acceptor和AsyncTimeout兩個內部類和一個Handler接口。Acceptor用於監聽請求,AsyncTimeout用於檢查異步Request的超時,Handler用於處理接收到的Socket,在內部調用Processor進行處理。
4. Container
Container用於封裝和管理Servlet,以及具體處理Request請求;包含4大請求處理組件:引擎(engine)、虛擬主機、上下文(context)組件。
Container是容器的父接口,用於封裝和管理Servlet,以及具體處理Request請求,該容器的設計用的是典型的責任鏈的設計模式,它由四個自容器組件構成,分別是Engine、Host、Context、Wrapper。這四個組件是負責關系,存在包含關系。只包含一個引擎。
5. 容器組件Engine
引擎表示可運行的Catalina的servlet引擎實例,並且包含了servlet容器的核心功能。在一個服務中只能有一個引擎。同時,作為一個真正的容器,Engine元素之下可以包含一個或多個虛擬主機。
作為請求處理的主要組件,它接收Connector傳入請求的對象以及輸出相應結果。它主要功能是將傳入請求委托給適當的虛擬主機處理。如果根據名稱沒有找到可處理的虛擬主機,那么將根據默認的Host來判斷該由哪個虛擬主機處理。
引擎通是指處理請求的Servlet引擎組件,即Catalina Servlet引擎,它檢查每一個請求的HTTP首部信息以辨別此請求應該發往哪個host或context,並將請求處理后的結果返回的相應的客戶端。嚴格意義上來說,容器不必非得通過引擎來實現,它也可以是只是一個容器。如果Tomcat被配置成為獨立服務器,默認引擎就是已經定義好的引擎。而如果Tomcat被配置為Apache Web服務器的提供Servlet功能的后端,默認引擎將被忽略,因為Web服務器自身就能確定將用戶請求發往何處。一個引擎可以包含多個host組件。
6. 容器組件Host
虛擬主機在Tomcat中使用Host組件表示,是web應用容器或者是Tomcat中所說的上下文。
Host 是 Engine 的子容器,一個 Host 在 Engine 中代表一個虛擬主機,這個虛擬主機的作用就是運行多個應用,它負責安裝和展開這些應用,並且標識這個應用以便能夠區分它們。它的子容器通常是 Context,它除了關聯子容器外,還有就是保存一個主機應該有的信息。一個虛擬主機下都可以部署一個或者多個Web App,每個Web App對應於一個Context,當Host獲得一個請求時,將把該請求匹配到某個Context上,然后把該請求交給該Context來處理。
在虛擬主機中有兩個概念非常重要--主機的域名和根目錄。
域名:每個虛擬主機是由它注冊的域名來標識的(例:www.host1.com)。域名是您預期的在客戶端瀏覽器地址欄輸入的值,對虛擬主機來說就是請求頭部。一台虛擬主機的名稱在包含它的引擎內必須是唯一的。
根目錄:根目錄所在的文件夾包含將被部署到此主機的上下文。根目錄可以是一個絕對路徑,也可以是對CATALINA_BASE 來說的一個相對路徑。
CATALINA_HOME 是一個環境變量,它引用了tomcat 二進制文件的位置。通過CATALINA_BASE 環境變量僅僅使用一個tomcat安裝信息的二進制文件,就可以根據不同的配置運行多個tomcat實例(這主要由conf文件夾的內容決定)。此外,使用一個CATALINA_BASE引用的位置(和CATALINA_HOME不同)保持標准的二進制分配獨立於您的安裝。這是有好處的,使tomcat升級到一個新版本變得容易,而不必擔心影響已經發布的web應用程序和相關的配置文件 。
虛擬主機技術,有兩種常用的方法來設置虛擬主機:1. 基於獨立IP地址的虛擬主機服務2. 基於名稱的虛擬主機服務
1) 基於獨立IP地址的虛擬主機服務
使用這種技術,每個FQHN(完全合格的主機名)被解析為一個單獨的IP地址。然而,這些IP中的每一個被解析后都映射到同一台物理機器上。
您可以使用以下的機制來實現此技術:
多宿主服務器,也就是說它安裝了多個網卡(NICs),每一個網卡都分配了IP地址
使用操作系統功能來設置虛擬網絡接口,為單個物理NIC(網卡)動態分配多個IP地址
無論在哪一種情況下,缺點是我們要獲得多個IP地址,而且這些地址(至少對於IPv4來說)是一種有限的資源。
Web服務器監聽為這些IP地址分配的端口,當Web服務器在一個特定的IP地址檢測到傳入的請求時,它會生成該IP地址的響應信息。
例如,您有一個web服務器,它運行在一個特定的在80端口監聽 11.156.33.345 和 11.156.33.346 IP地址請求的物理主機上。此web服務器用以下方式響應請求:當收到來自主機域名www.host1.com的請求時,則映射到11.156.33.345 IP地址;反之當收到來自主機域名www.host2.com的請求時則映射到后面的 IP地址 11.156.33.346 。
當接收到一個來自11.156.33.346 IP地址的請求時,web服務器知道它應當為ww.host2.com對應的域准備響應信息。對用戶來說,這是一個完全獨立的物理服務器在為他提供服務。
2) 基於名稱的虛擬主機服務
這是一種比較新的技術,它允許您把不同的域名映射到同一個IP地址。這些都是經過注冊的正常的域名,多個DNS條目將這些域名映射到同一IP地址。
HTTP 1.1協議要求每個請求必須包含一個主機頭:帶有完全合格的主機域名,以及用戶希望連接的端口號(如果已指定)。主機上運行的web服務器接收到此請求,解析此請求中的主機頭信息,以確定相應的虛擬主機來響應此請求。簡單、而且不使用不必要的IP地址,基於名稱的虛擬主機服務是我們的首選。
然而,當您同時使用SSL(安全套接層)和虛擬主機時,您也許不得不使用基於IP地址的虛擬主機服務。原因是,在特定的虛擬主機響應請求之前,協商協議要進行證書認證。這是因為:SSL協議層位於HTTP協議層的下方,而且在握手消息認證完成之前,與客戶端請求進行安全認證的模塊無法讀取HTTP請求頭信息。
您也許可以同時使用SSL和基於名稱的虛擬主機服務,如果您的web服務器和客戶機支持RFC 3546(傳輸層安全性擴展) 指定的服務器名稱標識擴展。使用此擴展,在SSL協商期間,客戶端會傳輸主機名稱給它嘗試連接的對象,從而使web服務器能夠處理握手信息並為正確的主機名返回證書。
虛擬主機別名
當web服務器解析別名信息時,例如它在主機頭里看到了域名的別名,那么web服務器會把此別名當作虛擬主機的域名來處理。 例如,您把swengsol.com設置為虛擬主機域名www.swengsol.com的別名,那么在客戶端url里無論是輸入域名還是別名,您都會收到來自同一個虛擬主機的響應信息。 這種方式效果不錯,當一個物理主機有多個域名時,而且您不想弄亂配置文件在為每個別名創建一組條目時。
7. 容器組件Context
Context上下文代表 Servlet 的 Context,它具備了 Servlet 運行的基本環境,它表示Web應用程序本身。理論上只要有 Context 就能運行 Servlet 了。簡單的 Tomcat 可以沒有 Engine 和 Host。Context 最重要的功能就是管理它里面的 Servlet 實例,Servlet 實例在 Context 中是以 Wrapper 出現的,還有一點就是 Context 如何才能找到正確的 Servlet 來執行它呢? Tomcat5 以前是通過一個 Mapper 類來管理的,Tomcat5 以后這個功能被移到了 request 中,在前面的時序圖中就可以發現獲取子容器都是通過 request 來分配的。一個Context對應於一個Web Application,一個Web Application由一個或者多個Servlet組成。
上下文或者web應用是應用自定義代碼(servlet、jsp)所存活的地方。它為web應用組織資源提供了便利。
同時context容器為servlet提供了一個ServletContext實例。在許多方面,servlet規范主要是關心這個上下文組件。例如,它規定了部署上下文的格式以及部署內容的描述符。
以下是上下文的一些重要屬性:
根目錄(document base):這個路徑是指war包或者未壓縮的項目文件所存放的目錄,可以是相對的,也可以是絕對的。
上下文路徑(context path):它是指在一個host下url中唯一標識一個web應用的部分。它幫助host容器來判斷該由哪一個已部署的上下文來處理傳入的請求。
也許你可能配置了默認context,它可以在找不到匹配的context的情況下來處理傳入請求。該默認context可以通過將其上下文路徑配置為空來標記的,因此,可以通過只有主機名的路徑來訪問它(譯注:如http://localhost:8080/來訪問)。並且該context已被tomcat默認定義為根目錄下的ROOT目錄。
· 自動重加載(automic reload):上下文中的資源會被tomcat監控,一旦資源發生改變Tomcat就會自動重新加載資源文件。雖然該功能在開發過程中非常有用,但是在生產環境這個操作代價非常高,通常需要重啟產品應用。
Context配置
Context是唯一的,這主要是因為它的配置包含多個選項。而我們之前已經注意到的conf/server.xml是用來配置Tomcat實例中一些全局性的參數。雖然在這個文件中可以配置context相關的東西,但是不推薦這樣做。相反,Tomcat推薦大家將context相關的配置從server.xml中提取出來,配置到上下文段文件中,該文件會被Tomcat監控並且可以在運行過程中重新加載。請再次注意,server.xml只有在啟動時被加載一次。同時需要確保在context中配置一個獨立明確的host和engine,因為Tomcat會在CATALINA_HOME/conf///目錄下查找context相關配置。而該目錄下為特定主機配置的上下文段文件則是以名稱.xml命名。默認情況下,會有一個引擎Catalina和一個名稱為localhost的主機,對應的工作目錄為CATALINA_HOME/conf/Catalina/localhost。但是該目錄也可以是有效域名,如www.swengsol.com,那么對應目錄就是CATALINA_HOME/conf/Catalina/www.swengsol.com。另外,context片段也可以在war或部署目錄中被包含在META-INF目錄下。這種情況下,context文件名稱必須為context.xml。此外,Context還可以被配置在web應用描述符文件web.xml中。雖然這個片段文件是Tomcat專用的,但是由於該描述符是通過Servlet規范來描述的,因此它也適用與JavaEE下的其他輕量級servlet容器。
8. 容器組件Wrapper
包裝器wrapper對象是context容器的子容器,表示一個單獨的servlet(或者由jsp文件轉換而來的servlet)。它之所以稱為包裝器是因為它包裝了java.servlet.Servlet實例。
Wrapper : 代表一個 Servlet,它負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收。Wrapper 是最底層的容器,它沒有子容器了,所以調用它的 addChild 將會報錯。
這是容器層次結構的最底層,添加任何子類都會導致異常。
同時包裝器還對它所包裝的servlet負責,包括加載、實例化servlet以及調用控制servlet生命周期相關的函數,如init()、service()和destroy()方法。
此外包裝器還通過它基本的Valve來調用和其包裝的servlet相關的過濾器。
9. 嵌套組件Valve
valve是處理元素,它可以被包含在每個Tomcat容器的處理路徑中--如engine、host、context以及servelt包裝器。若要增加Valve到Tomcat容器則需要在server.xml中使用<Valve>標簽。在server.xml中這些標簽的執行順序與其物理順序相同。
而在Tomcat中也分布這大量預先編譯好的valve。包括:
• 在請求日志元素中將請求(如遠程客戶端ip地址)寫入日志文件或數據庫時
• 根據遠程客戶端ip或主機名來控制某一特定web應用的訪問權限時
• 記錄每個請求和響應頭信息日志時
• 在同一個虛擬主機下為多個應用配置單點登錄時
如果以上這些都不能滿足你的要求,那么你可以通過繼承org.apache.catalina.Valve來實現自定義的Valve並將其配置到對應服務中。
但是對於一個容器來說,它並不會持有某個單獨valve的引用;相反,它會持有一個稱作管道(Pipeline)的單一實體的引用,並用這個管道來表示與該容器所關聯的一系列valve。當一個容器被調用來處理一個請求時,它會委托與其關聯的管道來處理對應請求。在管道中,這些valve則是基於他們在server.xml中的定義作順序排列。其中排在隊列中排在最后的valve被稱為管道的基本valve,該valve用來完成去執行容器的核心功能的任務。與單個valve不同,管道在server . xml不是一個明確的元素,而是含蓄的按照valve在給定容器中所定義的順序組成。並且在管道中,每個valve都知道其下一個valve;在它執行完前置處理以后,接下來它會調用鏈中的下一個valve,當該調用返回以后,它會在return之前執行他自身的處理任務。這種方式和servlet規范中的過濾器鏈所做的事情非常相似。
在這幅圖中,當接收到傳入請求時引擎所配置的valve首先被觸發。其中引擎中基本的valve負責確定目標主機委托該主機來處理;接下來目標主機(www.host1.com)的valve被按順序觸發。而該主機的基本valve則又決定了目標context(在這里是Context1)並且委托該context來處理該請求。最后Context1中所配置的valve被觸發,然后通過context中配置的基本valve委托給適當的包裝器來處理;而包裝器的基本valve又將處理轉交至被包裝的servlet來處理。處理完成以后,響應結果會按照以上的路徑反方向返回。
由於Valve就成了Tomcat服務器實現中的一部分,並且可以為開發者提供一種方式將自定義的代碼注入到處理請求的servlet容器中。因此,自定的valve類文件需要發布到CATALINA_HOME/lib目錄下而不是應用的發布目錄WEB-INF/classes。由於它們並不是servlet規范中的部分,所以valve在企業級一用中屬於不可移植元素。因此,如果已經依賴了一個特定的valve時,你必須在不同的應用服務器上找到對等的選擇方案。
還有很重要的一點就是,為了不影響請求處理的效率必須要保證valve的代碼高效執行。
10. 嵌套組件Realm
容器管理安全方面的工作通過容器處理應用程序的身份驗證和授權方面來解決。身份驗證存在的主要任務就是確保用戶所說的就是她自己,而授權的主要任務是決定一個用戶是否可以在某個應用下執行特定操作。由容器來管理安全的優勢是可以通過應用的發布者直接來配置安全措施。也就是說,為用戶分配密碼以及為用戶分配角色都可以用戶配置來完成,而這些配置也可以在修改任何代碼的情況下來供多個web應用共用。
應用管理安全,還有一種可選方案就是通過應用來管理安全問題。這種情況下,我的web應用程序代碼就是唯一的仲裁者來決定用戶在我們的應用下是否有訪問特定功能或資源的權限。
想要使容器來管理安全問題起作用,我們需要組裝一下組件:
• 安全約束:在我們的web應用部署描述器web.xml中,我們必須確定限制資源訪問的url表達式以及可以訪問這些資源的用戶角色。
• 憑證輸入機制:在web.xml部署文件中,我們需要指定容器應該如何提示用戶通過憑證來驗證。這通常是通過彈出一個對話框提示用戶輸入用戶名和密碼來完成,但也可以配置使用其他機制,如一個定制的登錄表單等。
• Realm:這是一個數據存儲機制來保存用戶名、密碼以及角色來對用戶所提供的憑證信息進行檢查。它可以是一個簡單的xml文件,一個通過JDBC API來訪問的關系型數據庫中的一張表或者是可以通過JNDI API訪問的輕量級目錄訪問協議服務器(LDAP)。正是Realm為Tomcat提供了一致的訪問機制來訪問這些不同的數據源。
以上這三種組件在技術上是相互獨立的。基於容器安全的威力就在於我們可以根據我們自身的安全情況從這幾種方式中選出適合的一種或幾種方式來混合使用。至此,當一個用戶請求一個資源時,Tomcat將檢查對所請求的資源是否已經存在了安全限制。對於存在限制的資源,Tomcat將自動要求用戶提供身份憑證並通過所配置的Realm來檢查用戶所提供憑證是否符合。只有在用戶所提供的憑證信息通過了驗證或者用戶的角色在可訪問資源的配置之列才能訪問對應資源。
11. 嵌套組件Excutor
這是從tomcat 6.0.11版本開始,新增的一個組件。執行器組件允許您配置一個共享的線程池,以供您的連接器使用。您的連接器可能使並發線程的數量達到上限。請注意,此限制同樣適用於:即使一個特定的連接器沒有用完為它配置的所有線程。
12. 嵌套組件Listener
每個主要的tomcat組件都實現了org.apache.catalina.Lifecycle接口。實現了該接口的組件注冊到監聽器,然后該組件的生命周期事件被觸發,比如該組件的啟動和停止都會被監聽。一個監聽器實現了org.apache.catalina.LifecycleListener接口,也實現了該接口的lifecycleEvent()方法,監聽器捕捉到一個LifecycleEvent 表示事件已經發生。這就給您提供了一個機會:把您自定義的進程注入到tomcat的生命周期。
13. 嵌套組件Session Manager
會話讓使用無狀態HTTP協議的應用程序完成通信。會話表示客戶端和服務器之間的通信,會話功能是由javax.servlet.http.HttpSession 的實例實現的,該實例存儲在服務器上而且與一個唯一的標識符相關聯,客戶端在與服務器的每次交互中根據請求中的標識符找到它的會話。一個新的會話在客戶端請求后被創建,會話一直有效直到一段時間后客戶端連接超時,或者會話直接失效例如客戶退出訪問服務器。
上圖顯示了一個非常簡單的 tomcat 會話機制視圖。Catalina 引擎(engine)使用了組件org.apache.catalina.Manager 去創建、查找、注銷會話。該組件負責管理為上下文創建的會話以及會話的生命周期。會話管理器(Manager)把會話存放在內存中,但是它支持在服務器重啟時恢復會話。當服務器停止時,會話管理器把所有活動的會話寫入磁盤,當服務器重新啟動時把會話重新加載到內存。
一個<Manager>必須是 <Context>的子節點,而且<Manager>負責管理與web應用程序上下文相關的會話。
會話管理器管理這樣的屬性:例如用來生成會話標識符的算法,每秒鍾檢查過期會話的頻率,支持的活動會話的最大數目,以及持久化會話的文件。
會話管理器實現了這樣的功能:為會話提供持久化存儲,例如一個文件或一個JDBC數據庫。
14. 嵌套組件Loader
這個組件是一個給定的web應用程序的類加載器。簡而言之,類加載器負責加載、解釋Java類編譯后的字節碼。
一個Java類的字節碼可能存放在各種不同的位置,最常見的是在本地文件系統或網絡中。類加載器的主要任務是:抽象字節如何被獲取以及如何重組到內存中的類的過程。
參考網址
- 四張圖帶你了解Tomcat系統架構
- 深入理解 Tomcat (二) 從宏觀上理解 Tomcat 組件及架構
- Tomcat 架構 (一)
- https://hub.packtpub.com/overview-tomcat-6-servlet-container-part-1/
- Tomcat架構(二)
- https://www.packtpub.com/books/content/overview-tomcat-6-servlet-container-part-1
- Tomcat架構(三)
- https://www.packtpub.com/books/content/overview-tomcat-6-servlet-container-part-2
- Tomcat架構(四)
- Tomcat 架構分析(一) 體系結構
- Tomcat運行過程和簡單模擬
- tomcat-架構原理
- Tomcat 面試題匯總
- 【面試總結】--tomcat調優方案
- Tomcat類加載機制和JAVA類加載機制的比較
- Tomcat的類加載機制
- 深入理解Tomcat(五)類加載機制
- 深入理解 Tomcat(四)Tomcat 類加載器之為何違背雙親委派模型
- tomcat架構
- 圖解Tomcat類加載機制(阿里面試題)
- Java虛擬機工作原理詳解
- Tomcat安裝、配置、優化及負載均衡詳解
- 8月前端面試題
- Tomcat常見面試題你都知道答案嗎?
- 后端服務:關於Tomcat相關面試題,看懂這篇就夠了(有深度)