tomcat總體架構

一 tomcat頂層架構

  • Server:服務器的意思,表明整個tomcat服務器,一個tomcat只有一個Server;
  • Service:Server中的一個邏輯功能層, 一個Server能夠包含多個Service;
  • Connector:稱做鏈接器,是Service的核心組件之一,一個Service能夠有多個Connector,主要是鏈接客戶端請求;
  • Container:Service的另外一個核心組件,按照層級有Engine,Host,Context,Wrapper四種,一個Service只有一個Engine,其主要做用是執行業務邏輯;
  • Jasper:JSP引擎;
  • Session:會話管理;

上面簡單列了tomcat的模塊結構,下面結合配置文件更加具體一點來分析,固然更可能是集中在Connector和Container兩個組件上,畢竟這是兩個核心組件,後續的內容也會更多集中在這兩個組件上面html

先將conf/server.xml配置文件內容貼出供參考(註釋部分沒有貼出):java

<?xml version="1.0" encoding="UTF-8"?>

 --><Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
  <Listener className="org.apache.catalina.core.JasperListener"/>
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>

  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
  </GlobalNamingResources>


  <Service name="Catalina">

    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="utf-8"/>
   

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>




    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    -->
    <Engine defaultHost="localhost" name="Catalina">

      <Realm className="org.apache.catalina.realm.LockOutRealm">

        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
      </Realm>

      <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="localhost_access_log." suffix=".txt"/>
<Context docBase="my-web" path="/my-web" reloadable="true" source="org.eclipse.jst.jee.server:my-web"/></Host>
    </Engine>
  </Service>
</Server>

二 server

Server是Tomcat最頂層的容器,表明着整個服務器,即一個Tomcat只有一個Server,Server中包含至少一個Service組件,用於提供具體服務。這個在配置文件中也獲得很好的體現(port=「8005」 shutdown="SHUTDOWN"是在8005端口監聽到"SHUTDOWN"命令,服務器就會中止)。git

Tomcat中其標準實現是:org.apache.catalina.core.StandardServer類,其繼承結構類圖以下:github

StandardServer實現Server很好理解,tomcat爲全部的組件都提供了生命週期管理,繼承LifecycleMBeanBase則跟tomcat中的生命週期機制有關,後續文章會有介紹。web

三 service

能夠想象,一個Server服務器,它最基本的功能確定是:apache

接收客戶端的請求,而後解析請求,完成相應的業務邏輯,而後把處理後的結果返回給客戶端,通常會提供兩個節本方法,一個start打開服務Socket鏈接,監聽服務端口,一個stop中止服務釋放網絡資源。tomcat

這時的服務器就是一個Server類:服務器

如何實現這個簡單的服務器,看過《深刻剖析tomcat》的應都知道,這部分代碼以前也敲過,在github上(https://github.com/w1992wishes/tomcat-work),其實就是在一個端口上監聽Socket請求,而後解析請求,返回處理結果。網絡

但若是將請求監聽和請求處理放在一塊兒,擴展性會變差,畢竟網絡協議不止HTTP一種,若是想適配多種網絡協議,請求處理又相同,這時就無能爲力了,tomcat的設計大師不會採起這種作法,而是將請求監聽和請求處理分開爲兩個模塊,分別是Connector和Container,Connector負責處理請求監聽,Container負責處理請求處理。架構

但顯然tomcat能夠有多個Connector,同時Container也能夠有多個。那這就存在一個問題,哪一個Connector對應哪一個Container,提供複雜的映射嗎?相信看過server.xml文件的人已經知道了tomcat是怎麼處理的了。

沒錯,Service就是這樣來的。在conf/server.xml文件中,能夠看到Service組件包含了Connector組件和Engine組件(前面有提過,Engine就是一種容器),即Service至關於Connector和Engine組件的包裝器,將一個或者多個Connector和一個Engine創建關聯關係。在默認的配置文件中,定義了一個叫Catalina 的服務,它將HTTP/1.1和AJP/1.3這兩個Connector與一個名爲Catalina 的Engine關聯起來。

一個Server能夠包含多個Service(它們相互獨立,只是公用一個JVM及類庫),一個Service負責維護多個Connector和一個Container。

其標準實現是StandardService,UML類圖以下:

這時tomcat就是這樣了:

四 connector

前面介紹過Connector是鏈接器,用於接受請求並將請求封裝成Request和Response,而後交給Container進行處理,Container處理完以後在交給Connector返回給客戶端。

一個Connector會監聽一個獨立的端口來處理來自客戶端的請求。server.xml默認配置了兩個Connector:

    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/>,它監聽端口8080,這個端口值能夠修改,connectionTimeout定義了鏈接超時時間,單位是毫秒,redirectPort 定義了ssl的重定向接口,根據上述配置,Connector會將ssl請求轉發到8443端口。
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />, AJP表示Apache Jserv Protocol,它將處理Tomcat和Apache http服務器之間的交互,此鏈接器用於處理咱們將Tomcat和Apache http服務器結合使用的狀況,如在同一臺物理Server上部署一個Apache http服務器和多臺Tomcat服務器,經過Apache服務器來處理靜態資源以及負載均衡時,針對不一樣的Tomcat實例須要AJP監聽不一樣的端口。

Connector在tomcat中的設計比較複雜,先大體列上一個圖:

這裏先簡單介紹Connector,後續會詳細分析。

Connector使用ProtocolHandler來處理請求的,不一樣的ProtocolHandler表明不一樣的鏈接類型,好比:Http11Protocol使用的是普通Socket來鏈接的(tomcat9已經刪除了這個類,再也不採用BIO的方式),Http11NioProtocol使用的是NioSocket來鏈接的。

其中ProtocolHandler由包含了三個部件:Endpoint、Processor、Adapter。

    Endpoint用來處理底層Socket的網絡鏈接,Processor用於將Endpoint接收到的Socket封裝成Request(這個Request和ServletRequest無關),Adapter充當適配器,用於將Request轉換爲ServletRequest交給Container進行具體的處理。
    Endpoint因爲是處理底層的Socket網絡鏈接,所以Endpoint是用來實現TCP/IP協議的,而Processor用來實現HTTP協議的,Adapter將請求適配到Servlet容器進行具體的處理。
    Endpoint的抽象實現AbstractEndpoint裏面定義的Acceptor和AsyncTimeout兩個內部類和一個Handler接口。Acceptor用於監聽請求,AsyncTimeout用於檢查異步Request的超時,Handler用於處理接收到的Socket,在內部調用Processor進行處理。

先不用太糾結,瞭解Connector是作什麼的就能夠,後續再深刻。

五 container

tomcat的container層次以下:

5.一、Engine

一個Service中有多個Connector和一個Engine,Engine表示整個Servlet引擎,一個Engine下面能夠包含一個或者多個Host,即一個Tomcat實例能夠配置多個虛擬主機,默認的狀況下 conf/server.xml 配置文件中<Engine name="Catalina" defaultHost="localhost"> 定義了一個名爲Catalina的Engine。

ContainerBase和LifecycleBase都是抽象出來的公共層。

5.二、Host

Host,表明一個站點,也能夠叫虛擬主機,一個Host能夠配置多個Context,在server.xml文件中的默認配置爲<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">, 其中appBase=webapps, 也就是<CATALINA_HOME>\webapps目錄,unpackingWARS=true 屬性指定在appBase指定的目錄中的war包都自動的解壓,autoDeploy=true 屬性指定對加入到appBase目錄的war包進行自動的部署。

一個Engine包含多個Host的設計,使得一個服務器實例能夠承擔多個域名的服務,是很靈活的設計。

其標準實現繼承圖以下:

5.三、Context

Context,表明一個應用程序,就是平常開發中的web程序,或者一個WEB-INF目錄以及下面的web.xml文件,換句話說每個運行的webapp最終都是以Context的形式存在,每一個Context都有一個根路徑和請求路徑;與Host的區別是Context表明一個應用,如,默認配置下webapps下的每一個目錄都是一個應用,其中ROOT目錄中存放主應用,其餘目錄存放別的子應用,而整個webapps是一個站點。

在Tomcat中一般採用以下方式建立一個Context:

    在<CATALINA_HOME>\webapps 目錄中建立一個目錄dirname,此時將自動建立一個context,默認context的訪問url爲http://host:port/dirname,也能夠經過在ContextRoot\META-INF 中建立一個context.xml文件,其中包含以下內容來指定應用的訪問路徑:
    在server.xml文件中增長context 元素,以下:<Context path="/urlpath" docBase="/test/xxx" reloadable=true />

這樣就能夠經過http://host:port/urlpath訪問上面配置的應用。

能夠打開tomcat目錄對照一下:


 

其標準實現類圖以下:

5.四、Wrapper

一個Context能夠包含多個Servlet處理不一樣請求,固然如今的SpringMVC,struts框架的出現致使程序中再也不是大量的Servlet,但其實本質是沒變的,都是由Servlet來處理或者看成入口。

在tomcat中Servlet被稱爲wrapper,其標準類圖以下:

那麼爲何要用Wrapper來表示Servlet?這和tomcat的處理機制有關,爲了更加靈活,便於擴展,tomcat是用管道(pipeline)和閥(valve)的形式來處理請求,因此將Servlet丟給Wrapper。這個後續再分析。

那麼如今tomcat就是這樣的:

6、Tomncat啓動流程

tomcat的啓動流程很標準化,入口是BootStrap,統一按照生命週期管理接口Lifecycle的定義進行啓動。首先,調用init()方法逐級初始化,接着調用start()方法進行啓動,同時,每次調用伴隨着生命週期狀態變動事件的觸發。

每一級組件除完成自身的處理外,還有負責調用子組件的相關調用,組件和組件之間是鬆耦合的,能夠經過配置進行修改。

大體流程圖以下:

7、總結

差很少就是這樣,大概瞭解整體的結構,固然這裏面沒有過多說起除Connector和Container外的其餘結構,若是感興趣,能夠自行學習。

相關文章
相關標籤/搜索