tomcat源碼系列(二)--tomcat總體結構

Tomcat的總體結構

Tomcat即是一個Http服務器也是一個Servlet容器,它的總體結構我們可以用下圖來描述:

這裏寫圖片描述

通過上圖我們可以看出Tomcat中主要涉及Server,Service,Engine,Connector,Host,Context組件,之前用過Tomcat的童鞋是不是覺得這些組件的名稱有點似曾相識的趕腳,沒趕腳?!您再想想。好吧,不用你想了,我來告訴你吧。其實在Tomcat二進制分發包解壓後,在conf目錄中有一個server.xml文件,你打開它瞄兩眼看看,是不是發現server.xml文件中已經包含了上述的幾個名稱。我拿我本地Tomcat7.0.42分發包中的server.xml來具體分析一下,它的內容如下:
conf/server.xml(Tomcat 7.0.42)

<?xml version='1.0' encoding='utf-8'?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- Note:  A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" at this level.
     Documentation at /docs/config/server.html
 -->
<Server port="8005" shutdown="SHUTDOWN">
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!--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 name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
  <Service name="Catalina">

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>
    -->


    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->
    <!-- Define a SSL HTTP/1.1 Connector on port 8443
         This connector uses the JSSE configuration, when using APR, the
         connector should be using the OpenSSL style configuration
         described in the APR documentation -->
    <!--
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
    -->

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


    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->

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

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="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"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

接下來我們就根據上圖以及conf/server.xml的內容來一步步描述一下上面所說的各種組件吧。

Server

首先閃聯登場的是咋們的Server大哥(大家能給點掌聲嗎?),Server是Tomcat中最頂層的組件,它可以包含多個Service組件。在Tomcat源代碼中Server組件對應源碼中的 org.apache.catalina.core.StandardServer 類。StandardServer的繼承關係圖如下圖所示:

這裏寫圖片描述

Service

接下來咋們來看看Service組件,Service組件相當於Connetor和Engine組件的包裝器,它將一個或者多個Connector組件和一個Engine建立關聯。缺省的的配置文件中,定義一個叫 Catalina 的服務,並將Http,AJP這兩個Connector關聯到了一個名爲 Catalina 的Engine.Service組件對應Tomcat源代碼中的 org.apache.catalina.core.StandardService ,StandardService的繼承關係圖如下圖所示:

這裏寫圖片描述

Connector

既然Tomcat需要提供http服務,而我們知道http應用層協議最終都是需要通過TCP層的協議進行包傳遞的,而Connector正是Tomcat中監聽TCP網絡連接的組件,一個Connector會監聽一個獨立的端口來處理來自客戶端的連接。缺省的情況下Tomcat提供瞭如下兩個Connector。我們分別描述一下:

HTTP/1.1
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 上面定義了一個Connector,它缺省監聽端口8080,這個端口我們可以根據具體情況進行改動。 connectionTimeout 定義了連接超時時間,單位是毫秒, redirectPort 定義了ssl的重定向接口,根據缺省的配置,Connector會將ssl請求重定向到8443端口。
AJP/1.3
AJP表示 Apache Jserv Protocol ,此連接器將處理Tomcat和Aapache http服務器之間的交互,這個連機器是用來處理我們將Tomcat和Apache http服務器結合使用的情況。假如在同樣的一臺物理Server上面部署了一臺Apache http服務器和多臺Tomcat服務器,通過Apache服務器來處理靜態資源以及負載均衡的時候,針對不同的Tomcat實例需要AJP監聽不同的端口。

Connector對應源代碼中的 org.apache.catalina.connector.Connector ,它的繼承關係圖如下所示:

這裏寫圖片描述

Engine

Tomcat中有一個容器的概念,而Engine,Host,Context都屬於Contanier,我們先來說說最頂層的容器Engine.
一個Engine可以包含一個或者多個Host,也就是說我們一個Tomcat的實例可以配置多個虛擬主機。
缺省的情況下 定義了一個名稱爲Cataline的Engine.Engine對應源代碼中的 org.apache.catalina.core.StandardEngine ,它的繼承關係圖如下圖所示:

這裏寫圖片描述

Host

Host定義了一個虛擬主機,一個虛擬主機可以有多個Context,缺省的配置如下:
…. 其中 appBase 爲webapps,也就是 \webapps 目錄, unpackingWARS 屬性指定在appBase指定的目錄中的war包都自動的解壓,缺省配置爲true, autoDeploy 屬性指定是否對加入到appBase目錄的war包進行自動的部署,缺省爲true.
Host對應源代碼中的 org.apache.catalina.core.StandardHost ,它的繼承關係圖如下所示:

這裏寫圖片描述

Context

在Tomcat中,每一個運行的webapp其實最終都是以Context的形成存在,每個Context都有一個根路徑和請求URL路徑,Context對應源代碼中的 org.apache.catalina.core.StandardContext ,它的繼承關係圖如下圖所示:

這裏寫圖片描述

在Tomcat中我們通常採用如下的兩種方式創建一個Context.下面分別描述一下:

在 <CATALINA-HOME>\webapps 目錄中創建一個目錄,這個時候將自動創建一個context,默認context的訪問url爲 http://host:port/dirname ,你也可以通過在 ContextRoot\META-INF 中創建一個context.xml的文件,其中包含如下的內容來指定應用的訪問路徑。 <Context path="/yourUrlPath" />
conf\server.xml文件中增加context元素。 第二種創建context的方法,我們可以選擇在server.xml文件的 <Host> 元素,比如我們在server.xml文件中增加如下內容:

server.xml

......
    ......
    <Context path="/mypath" docBase="/Users/tiger/develop/xxx" reloadable="true">
    </Context>
  </Host>
</Engine>
  </Service>
</Server>

這樣的話,我們就可以通過 http://host:port/mypath 訪問上面配置的context了。

Valve

Valve中文意思是閥門,Valve是Tomcat中責任鏈模式的實現,通過鏈接多個Valve對請求進行處理。其中Valve可以定義在任何的Container中,上面說的Engine,Host,Context都屬於容器。tomcat 默認定義了一個名爲 org.apache.catalina.valves.AccessLogValve 的Valve,這個Valve負責攔截每個請求,然後記錄一條訪問日誌。

通過上面的分析,我們發現Server,Service,Engine,Host,Context都實現了 org.apache.catalina.Lifecycle 接口,通過這個接口管理了這些核心組件的生命週期,關於這些組件的生命週期,我們在下一篇文章描述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章