Tomcat處理HTTP請求原理

一.Tomcat是什麼?

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

二.Tomcat的體系結構

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

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

三.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 引擎。session

Engine

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

Host

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

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)。

相關文章
相關標籤/搜索