1. 程式人生 > 實用技巧 >Tomcat Web應用伺服器學習筆記

Tomcat Web應用伺服器學習筆記

Tomcat 系統架構與原理剖析

1)瀏覽器訪問伺服器的流程

2)Tomcat 系統總體架構

HTTP 伺服器接收到請求之後把請求交給Servlet容器來處理,Servlet 容器通過Servlet接⼝調⽤業務類。Servlet接⼝和Servlet容器這⼀整套內容叫作Servlet規範。

注意:Tomcat既按照Servlet規範的要求去實現了Servlet容器,同時它也具有HTTP伺服器的功能。Tomcat的兩個重要身份:是一個http伺服器,也是⼀個Servlet容器。

3)Tomcat Servlet容器處理流程,當⽤戶請求某個URL資源時

1)HTTP伺服器會把請求資訊使⽤ServletRequest物件封裝起來

2)進⼀步去調⽤Servlet容器中某個具體的Servlet

3)在 2)中,Servlet容器拿到請求後,根據URL和Servlet的對映關係,找到相應的Servlet

4)如果Servlet還沒有被載入,就⽤反射機制建立這個Servlet,並調⽤Servlet的init⽅法來完成初始化

5)接著調⽤這個具體Servlet的service⽅法來處理請求,請求處理結果使⽤ServletResponse物件封裝

6)把ServletResponse物件返回給HTTP伺服器,HTTP伺服器會把響應傳送給客戶端

4)Tomcat 系統總體架構

Tomcat 設計了兩個核⼼元件聯結器(Connector)和容器(Container)來完成 Tomcat 的兩⼤核⼼功能。聯結器,負責對外交流: 處理Socket連線,負責⽹絡位元組流與Request和Response物件的轉化;

容器,負責內部處理:載入和管理Servlet,以及具體處理Request請求;

Tomcat 聯結器元件 Coyote 簡介:Coyote 是Tomcat 中聯結器的元件名稱 , 是對外的接⼝。客戶端通過Coyote與伺服器建⽴連線、傳送請求並接受響應 。

(1)Coyote 封裝了底層的⽹絡通訊(Socket 請求及響應處理)

(2)Coyote 使Catalina 容器(容器元件)與具體的請求協議及IO操作⽅式完全解耦

(3)Coyote 將Socket 輸⼊轉換封裝為 Request 物件,進⼀步封裝後交由Catalina 容器進⾏處理,處理請求完成後, Catalina 通過Coyote 提供的Response 物件將結果寫⼊輸出流

(4)Coyote 負責的是具體協議(應⽤層)和IO(傳輸層)相關內容

5)Tomcat Servlet 容器 Catalina

Tomcat是⼀個由⼀系列可配置(conf/server.xml)的元件構成的Web容器,⽽Catalina是Tomcat的servlet容器。從另⼀個⻆度來說,Tomcat 本質上就是⼀款 Servlet 容器, 因為 Catalina 才是 Tomcat 的核⼼ , 其他模組都是為Catalina 提供⽀撐的。 ⽐如 : 通過 Coyote 模組提供連結通訊,Jasper 模組提供 JSP 引擎,Naming 提供JNDI 服務,Juli 提供⽇志服務。

Servlet 容器 Catalina 的結構Tomcat(我們往往有⼀個認識,Tomcat就是⼀個Catalina的例項,因為Catalina是Tomcat的核⼼)

其實,可以認為整個Tomcat就是⼀個Catalina例項,Tomcat 啟動的時候會初始化這個例項,Catalina例項通過載入server.xml完成其他例項的建立,建立並管理⼀個Server,Server建立並管理多個服務,每個服務⼜可以有多個Connector和⼀個Container。

⼀個Catalina例項(容器)⼀個 Server例項(容器)多個Service例項(容器)每⼀個Service例項下可以有多個Connector例項和⼀個Container例項。

Catalina:負責解析Tomcat的配置⽂件(server.xml) , 以此來建立伺服器Server元件並進⾏管理

Server:伺服器表示整個Catalina Servlet容器以及其它元件,負責組裝並啟動Servlaet引擎,Tomcat聯結器。Server通過實現Lifecycle接⼝,提供了⼀種優雅的啟動和關閉整個系統的⽅式

Service:服務是Server內部的元件,⼀個Server包含多個Service。它將若⼲個Connector元件繫結到⼀個

Container:Container容器,負責處理⽤戶的servlet請求,並返回物件給web⽤戶的模組

Container 元件的具體結構

Container元件下有⼏種具體的元件,分別是Engine、Host、Context和Wrapper。這4種元件(容器)是⽗⼦關係。Tomcat通過⼀種分層的架構,使得Servlet容器具有很好的靈活性。

Engine表示整個Catalina的Servlet引擎,⽤來管理多個虛擬站點,⼀個Service最多隻能有⼀個Engine,但是⼀個引擎可包含多個Host

Host代表⼀個虛擬主機,或者說⼀個站點,可以給Tomcat配置多個虛擬主機地址,⽽⼀個虛擬主機下可包含多個Context

Context表示⼀個Web應⽤程式, ⼀個Web應⽤可包含多個Wrapper

Wrapper表示⼀個Servlet,Wrapper 作為容器中的最底層,不能包含⼦容器上述元件的配置其實就體現在conf/server.xml中。

Tomcat 伺服器核⼼配置詳解

主要標籤結構如下:

<!--Server 根元素,建立⼀個Server例項,⼦標籤有 Listener、GlobalNamingResources、Service-->
<Server>
  <!--定義監聽器-->
  <Listener/>
  <!--定義伺服器的全域性JNDI資源 -->
  <GlobalNamingResources/>
  <!--定義⼀個Service服務,⼀個Server標籤可以有多個Service服務例項-->
  <Service/>
</Server>

Server 標籤

<!--port:關閉伺服器的監聽端⼝ shutdown:關閉伺服器的指令字串-->
<Server port="8005" shutdown="SHUTDOWN">
  <!-- 以⽇志形式輸出伺服器 、作業系統、JVM的版本資訊 -->
  <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 -->
  <!-- 載入(伺服器啟動) 和 銷燬 (伺服器停⽌) APR。 如果找不到APR庫, 則會輸出⽇志, 並不影響 Tomcat啟動 -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <!-- 避免JRE記憶體洩漏問題 -->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <!-- 載入(伺服器啟動) 和 銷燬(伺服器停⽌) 全域性命名服務 -->
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <!-- 在Context停⽌時重建 Executor 池中的執行緒, 以避免ThreadLocal 相關的記憶體洩漏 -->
  Service 標籤
  Executor 標籤
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html GlobalNamingResources 中定義了全域性命名服務-->
  <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">
    ...
  </Service>
</Server>

Service 標籤

<!--該標籤⽤於建立 Service 例項,預設使⽤ org.apache.catalina.core.StandardService。預設情況下,Tomcat 僅指定了Service 的名稱, 值為 "Catalina"。Service ⼦標籤為 : Listener、Executor、Connector、Engine,其中:Listener ⽤於為Service新增⽣命週期監聽器,Executor ⽤於配置Service 共享執行緒池,Connector ⽤於配置Service 包含的連結器,Engine ⽤於配置Service中連結器對應的Servlet 容器引擎-->
<Service name="Catalina">
...
</Service>

Executor 標籤

<!--Connector 標籤Connector 標籤⽤於建立連結器例項預設情況下,server.xml 配置了兩個連結器,⼀個⽀持HTTP協議,⼀個⽀持AJP協議⼤多數情況下,我們並不需要新增連結器配置,只是根據需要對已有連結器進⾏優化預設情況下,Service 並未新增共享執行緒池配置。 如果我們想新增⼀個執行緒池, 可以在<Service> 下新增如下配置:name:執行緒池名稱,⽤於 Connector中指定namePrefix:所建立的每個執行緒的名稱字首,⼀個單獨的執行緒名稱為
namePrefix+threadNumber maxThreads:池中最⼤執行緒數 minSpareThreads:活躍執行緒數,也就是核⼼池執行緒數,這些執行緒不會被銷燬,會⼀直存在 maxIdleTime:執行緒空閒時間,超過該時間後,空閒執行緒會被銷燬,預設值為6000(1分鐘),單位毫秒 maxQueueSize:在被執⾏前最⼤執行緒排隊數⽬,預設為Int的最⼤值,也就是⼴義的⽆限。除⾮特殊情況,這個值 不需要更改,否則會有請求不會被處理的情況發⽣
prestartminSpareThreads:啟動執行緒池時是否啟動 minSpareThreads部分執行緒。預設值為false,即不啟動 threadPriority:執行緒池中執行緒優先順序,預設值為5,值從1到10
className:執行緒池實現類,未指定情況下,預設實現類為 org.apache.catalina.core.StandardThreadExecutor。如果想使⽤⾃定義執行緒池⾸先需要實現org.apache.catalina.Executor接⼝-->
<Executor name="commonThreadPool" namePrefix="thread-exec-" maxThreads="200" minSpareThreads="100" maxIdleTime="60000" maxQueueSize="Integer.MAX_VALUE"
prestartminSpareThreads="false" threadPriority="5" className="org.apache.catalina.core.StandardThreadExecutor"/>

Connector 標籤Connector 標籤⽤於建立連結器例項。預設情況下,server.xml 配置了兩個連結器,⼀個⽀持HTTP協議,⼀個⽀持AJP協議⼤多數情況下,我們並不需要新增連結器配置,只是根據需要對已有連結器進⾏優化

<!--port:端⼝號,Connector ⽤於建立服務端Socket 並進⾏監聽, 以等待客戶端請求連結。如果該屬性設定為0, Tomcat將會隨機選擇⼀個可⽤的端⼝號給當前Connector 使⽤
protocol:當前Connector ⽀持的訪問協議。 預設為 HTTP/1.1 , 並採⽤⾃動切換機制選擇⼀個基於 JAVA NIO 的連結器或者基於本地APR的連結器(根據本地是否含有Tomcat的本地庫判定)
connectionTimeOut:Connector 接收連結後的等待超時時間, 單位為 毫秒。 -1 表示不超時。redirectPort:當前Connector 不⽀持SSL請求, 接收到了⼀個請求, 並且也符合security-constraint 約束,
需要SSL傳輸,Catalina⾃動將請求重定向到指定的端⼝。
executor:指定共享執行緒池的名稱, 也可以通過maxThreads、minSpareThreads 等屬性配置內部執行緒池。可以使⽤共享執行緒池Engine 標籤 Engine 表示 Servlet 引擎 Host 標籤 Host 標籤⽤於配置⼀個虛擬主機
URIEncoding:⽤於指定編碼URI的字元編碼, Tomcat8.x版本預設的編碼為 UTF-8 , Tomcat7.x版本預設為ISO-8859-1-->
<!--org.apache.coyote.http11.Http11NioProtocol , ⾮阻塞式 Java NIO 連結器-->
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

可以使⽤共享執行緒池

<Connector port="8080" protocol="HTTP/1.1" executor="commonThreadPool" maxThreads="1000" minSpareThreads="100" acceptCount="1000" maxConnections="1000" connectionTimeout="20000" compression="on" compressionMinSize="2048" disableUploadTimeout="true" redirectPort="8443" URIEncoding="UTF-8" />

Engine 標籤Engine 表示 Servlet 引擎

<!--name: ⽤於指定Engine 的名稱, 預設為CatalinadefaultHost:預設使⽤的虛擬主機名稱, 當客戶端請求指向的主機⽆效時, 將交由預設的虛擬主機處理, 預設為localhost-->
<Engine name="Catalina" defaultHost="localhost">
...
</Engine>

Host 標籤Host 標籤⽤於配置⼀個虛擬主機

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

Context 標籤Context 標籤⽤於配置⼀個Web應⽤,如下:

<Host name="www.abc.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
  <!--docBase:Web應⽤⽬錄或者War包的部署路徑。可以是絕對路徑,也可以是相對於 Host appBase的相對路徑。path:Web應⽤的Context 路徑。如果我們Host名為localhost, 則該web應⽤訪問的根路徑為:
http://localhost:8080/web_demo。-->
  <Context docBase="/Users/yingdian/web_demo" path="/web3"></Context>
  <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>