Tomcat處理HTTP請求原理


一.Tomcat是什么?

Tomcat是一個Web應用服務器,同時也是一個Servlet/JSP容器。Tomcat作為Servlet容器,負責處理客戶端請求,把請求傳送給Servlet,並將Servlet的響應返回給客戶端。

二.Tomcat的體系結構

Tomcat是一個基於組件的服務器,它的構成組件都是可配置的。其各個組件都在Tomcat安裝目錄下的../conf/server.xml文件中配置。

server.xml文件源代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--頂層類元素,可以包含多個Service-->
<Server port="8005" shutdown="SHUTDOWN">  
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <GlobalNamingResources>
    <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>
  <!--頂層類元素,可包含一個Engine(container),多個connector-->
  <Service name="Catalina">
  <!--連接器類元素,代表通信接口-->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <!--容器類元素,為特定的service組件處理客戶請求-->
    <Engine name="Catalina" defaultHost="localhost">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
        </Realm>
        <!--容器類元素,為特定的虛擬主機組件處理客戶請求-->
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <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>

由上面的源碼中可得出Tomcat的體系結構如下:

tomcat

由上圖可以看出Tomcat的心臟是兩個核心組件:Connector和Container。其中一個Container可以選擇多個Connector。下面就對這兩個組件進行詳細講解。

三.Tomcat的兩個核心組件:Connector和Container
1.Connector組件

一個Connector組件將在某個指定的端口上偵聽客戶請求,接收瀏覽器發過來的tcp連接請求,創建一個Request和一個Response對象分別用於和其你去端交換數據,然后會產生一個線程來處理這個請求並把產生的Request和Response對象傳給Engine,從Engine中獲得響應並返回給客戶端。 Tomcat有兩個經典的Connector,一個直接偵聽來自瀏覽器的HTTP請求,另外一個偵聽來自其他的WebServer的請求。Cotote HTTP/1.1 Connector在端口8080處偵聽來自客戶瀏覽器的HTTP請求,Coyote JK2 Connector在端口8009處偵聽其他WebServer的Servlet/JSP請求。 Connector 最重要的功能就是接收連接請求然后分配線程讓 Container來處理這個請求,所以這必然是多線程的,多線程的處理是 Connector 設計的核心。

2.Container組件

Container組件的體系結構如下:

container

Container

Container是容器的父接口,該容器的設計用的是典型的責任鏈的設計模式,它由四個自容器組件構成,分別是Engine、Host、Context、Wrapper。這四個組件是負責關系,存在包含關系。通常一個Servlet class對應一個Wrapper,如果有多個Servlet則定義多個Wrapper,如果有多個Wrapper就要定義一個更高的Container,如Context。 Context定義在父容器 Host 中,其中Host 不是必須的,但是要運行 war 程序,就必須要 Host,因為 war 中必有 web.xml 文件,這個文件的解析就需要 Host 了,如果要有多個 Host 就要定義一個 top 容器 Engine 了。而 Engine 沒有父容器了,一個 Engine 代表一個完整的 Servlet 引擎。

Engine

Engine 容器比較簡單,它只定義了一些基本的關聯關系 Host 容器

Host

Host 是 Engine 的字容器,一個 Host 在 Engine 中代表一個虛擬主機,這個虛擬主機的作用就是運行多個應用,它負責安裝和展開這些應用,並且標識這個應用以便能夠區分它們。它的子容器通常是 Context,它除了關聯子容器外,還有就是保存一個主機應該有的信息。

Context

Context 代表 Servlet 的 Context,它具備了 Servlet 運行的基本環境,理論上只要有 Context 就能運行 Servlet 了。簡單的 Tomcat 可以沒有 Engine 和 Host。Context 最重要的功能就是管理它里面的 Servlet 實例,Servlet 實例在 Context 中是以 Wrapper 出現的,還有一點就是 Context 如何才能找到正確的 Servlet 來執行它呢? Tomcat5 以前是通過一個 Mapper 類來管理的,Tomcat5 以后這個功能被移到了 request 中,在前面的時序圖中就可以發現獲取子容器都是通過 request 來分配的

Wrapper

Wrapper 代表一個 Servlet,它負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收。Wrapper 是最底層的容器,它沒有子容器了,所以調用它的 addChild 將會報錯。 Wrapper 的實現類是 StandardWrapper,StandardWrapper 還實現了擁有一個 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 將直接和 Servlet 的各種信息打交道。

說明:除了上述組件外,Tomcat中還有其他重要的組件,如安全組件security、logger日志組件、session、mbeans、naming等其他組件。這些組件共同為Connector和Container提供必要的服務。
四.Tomcat 處理一個HTTP請求的過程

Tomcat Server處理一個HTTP請求的過程如下圖所示: tomcatserver

1.用戶在瀏覽器中輸入網址localhost:8080/test/index.jsp,請求被發送到本機端口8080,被在那里監聽的Coyote HTTP/1.1 Connector獲得;

2.Connector把該請求交給它所在的Service的Engine(Container)來處理,並等待Engine的回應;

3.Engine獲得請求localhost/test/index.jsp,匹配所有的虛擬主機Host;

4.Engine匹配到名為localhost的Host(即使匹配不到也把請求交給該Host處理,因為該Host被定義為該Engine的默認主機),名為localhost的Host獲得請求/test/index.jsp,匹配它所擁有的所有Context。Host匹配到路徑為/test的Context(如果匹配不到就把該請求交給路徑名為“ ”的Context去處理);

5.path=“/test”的Context獲得請求/index.jsp,在它的mapping table中尋找出對應的Servlet。Context匹配到URL Pattern為*.jsp的Servlet,對應於JspServlet類;

6.構造HttpServletRequest對象和HttpServletResponse對象,作為參數調用JspServlet的doGet()或doPost(),執行業務邏輯、數據存儲等;

7.Context把執行完之后的HttpServletResponse對象返回給Host;

8.Host把HttpServletResponse對象返回給Engine;

9.Engine把HttpServletResponse對象返回Connector;

10.Connector把HttpServletResponse對象返回給客戶Browser。


參考文章(http://blog.csdn.net/sky_100/article/details/77541968)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM