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 "%r" %s %b" /> </Host>