大飛帶你深入理解Tomcat(七)
作者:叩丁狼教育王一飛,高階講師。轉載請註明出處。
經過前幾篇的tomcat分解,大體能理解tomcat操作原理,那麼真實的tomcat又是一個怎麼的架構呢?本篇我們站在上帝角度來看下tomcat整個系統結構。
下面是上圖各元件的介紹:
Server
最頂級元件,程式碼著tomcat例項,在JVM有且僅有一份。引入事件處理機制,方便Server在生命週期不同階段處理不同邏輯。引入GlobalNamingResources元件,為JNDI提供支援。
Service
tomcat功能服務的抽象,一個server元件中至少有一個service, 是請求從發起到響應所有參與元件集合體。分為2個核心部分:Connector元件和Container(Engine/Host/Context/Wrapper統稱)元件。注意,一個Service包含若干個Connector元件,用於處理基於不同通訊協議的連線相關事情, 比如HTTP協議、AJP協議等連線。而一個Service只能擁有一個Engine元件。
Connector
負責接收客戶端連線並接收訊息報文,簡單講就是將socket轉換成Reqeust跟Response物件,然後交給Engine容器處理。Connector元件包含的模組
》協議模組(Protocol)
識別客戶端請求是基於什麼協議,目前tomcat支援HTTP協議、HTTPS協議,HTTP2協議和AJP協議,對應的處理類Http11AprProtocol類,Http2Protocol類,AjpAprProtocol類
》Acceptor元件
用於監聽連線埠,當請求到來時,直接丟入Executor執行緒池統一處理。
》Processor元件
處理請求(分析協議,獲取請求資料,封裝請求物件等),將處理結果(請求物件)傳入到Engine容器。
tomcat同時支援網路IO方式:同步阻塞(BIO), 同步非阻塞(NIO), 非同步非阻塞(NIO2/AIO), 通用IO操作規範(APR), 其中Tomcat8.5之後拋棄對BIO的支援。
》Mapper元件
路徑對映元件,也可以稱之路徑路由。通過解析url的地址,對映到具體serlvet類。
》CoyoteAdaptor元件
Connector元件與Engine元件連線的介面卡。
Container
tomcat容器的統稱,tomcat中有4個級別的容器,分別是Engine,Host,Context, Wrapper。Connector元件接收與處理客戶端發起的請求,將處理結果傳入tomcat容器,以求進一步處理。如下圖:
Engine
頂層的容器, 代表一個全域性 Servlet 引擎,負責接收connector包裝的請求。每一service只能有一個Engine元件,而Engine元件可以包含多個Host元件。除了Host元件外,Engin還包含其他元件
》Listener:監聽tomcat生命週期中關於Engine容器相關的工作, 比如建立,銷燬等
》AccessLog元件:記錄客戶端訪問日誌
》Cluster元件:提供叢集功能
》PipeLine元件:Engine容器對請求進行處理管道
》Realm元件:提供Engine容器級別的許可權校驗資訊物件
Host
Engine容器的子容器,表示一個虛擬主機。是根據URL地址中的主機(IP/域名,比如localhost)抽象而來。一個Engine容器可以包含若干個Host容器,而一個Host容器可以包含若干跟context容器。其他元件跟Egine子元件一樣,這裡不多說
Context
對應一個web應用程式,是對於web專案的抽象,負責將web專案所有元件轉成tomcat能操作的容器元件。包含多個Wrapper元件。
》Loader元件:Web應用載入器,用於載入web資源。
》Manager元件:會話管理器,管理部署到tomcat中的web容器會話。比如維護會話的生成、更新、銷燬
》NamingResource元件:命名資源,完成Tomcat server.xml和web應用context.xml資源與屬性的對映
》Mapper元件:Servlet對映器
Wrapper
tomcat中最下的容器物件,與之對應的是servlet, 一個Wrapper對應一個Servlet。它包含3個子元件:
》Servlet元件:web專案處理邏輯的servlet
》ServletPool元件:Servlet物件池,如果servlet實現SingleThreadModel介面時,Wrapper會建立一個Servlet物件池,保證Servelt訪問執行緒安全。
》PipeLine元件:Wrapper容器對請求進行處理管道
以一個案例來總結
假設在tomcat中部署一個web專案:
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<GlobalNamingResources>...</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm"></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 "%r" %s %b" />
<Context path="" docBase="xxx/helloApp/webapp" >
</Context>
</Host>
</Engine>
</Service>
</Server>
1>在tomcat根/conf/server.xml檔案上配置一個
<Context path="" docBase="xxx/helloApp/webapp" ></Context>
2>啟動tomcat,Connector元件接收器(Accoptor)監聽server.xml配置的8080埠,當然其他埠(8009)也監聽。目前關注8080埠
3>在瀏覽器位址列中輸入http://localhost:8080/hello 回車
4>瀏覽器發起請求(發起socket連線),Accoptor接收器接收到連線,將連線封裝到任務執行緒,丟到執行緒池(Executor)處理.
5>執行緒池(Exceutor)發現任務佇列中有執行緒任務, 馬上可以執行響應任務,
1) 先判斷髮起連線的協議(Protocol):此處為Http1.1協議
2) 根據協議呼叫不同連線處理元件(Processor):此處呼叫的是Http11Processor元件
Http11Processor 元件開始解析HTTP請求頭,請求行,請求體,將解析結果封裝成Request物件,傳入到容器中。
6>Mapper元件根據HTTP請求行中URL屬性以及Host請求頭,匹配哪個Host容器,哪個Context容器,哪個Wraper容器處理請求。這一步結合專案配置的web.xml檔案可以找到具體的servlet
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>cn.wolfcode.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
7>CoyoteAdaptor元件是Connector跟Container連線橋樑,將前幾步建立的請求Request物件與響應Response物件傳到Engine容器,呼叫Engine容器的Pipeline管道執行其他額外的操作。
8>Engine容器執行容器中定義的各種Pipeline管道,最後執行Host容器的Pipeline管道,將Reqeust跟Response物件傳入到Host容器。
9>Host容器執行容器中定義的各種Pipeline管道,最後執行Host容器的Pipeline管道,將Reqeust跟Response物件傳入到Context容器。
10>Context容器執行容器中定義的各種Pipeline管道,最後執行Host容器的Pipeline管道,將Reqeust跟Response物件傳入到Wrapper容器。
11>Wrapper容器呼叫其對應的Servlet中的service方法,處理請求邏輯,然後將結果響應給瀏覽器。
下面是上述請求的草圖:
相關文章
- 大飛帶你深入理解Tomcat(二)Tomcat
- 帶你深入理解和解剖 synchronizedsynchronized
- 帶你深入理解傳遞引數
- 曹工說Tomcat3:深入理解 Tomcat DigesterTomcat
- 老司機帶你深入理解 Laravel 之 FacadeLaravel
- 帶你深入理解 Flutter 中的字型“冷”知識Flutter
- 帶你深入理解Android中的自定義屬性!!!Android
- 阿里大佬帶你,深入理解執行緒池底層原理阿里執行緒
- 用例項帶你深入理解Java記憶體模型Java記憶體模型
- Spring Cache 帶你飛(二)Spring
- Spring Cache 帶你飛(一)Spring
- 老當機帶你深入理解 Laravel 之驗證器下Laravel
- 玩轉Redis-老闆帶你深入理解分散式鎖Redis分散式
- 從JAVA記憶體到垃圾回收,帶你深入理解JVMJava記憶體JVM
- 萬字常人帶你深入理解Zookeeper!為你的春招做好準備!
- 深入理解javascript系列(七):閉包(1)JavaScript
- <七>深入理解new和delete的原理delete
- 帶你通俗理解httpsHTTP
- 萬字長文帶你深入理解netty!為你的春招做好準備!Netty
- 帶你深入淺出理解深度學習(附資源打包下載)深度學習
- 從程式碼生成說起,帶你深入理解 mybatis generator 原始碼MyBatis原始碼
- 大資料】帶你理解並使用flink中的Time大資料
- 九爺帶你瞭解Tomcat優化Tomcat優化
- 炸裂!MySQL 82 張圖帶你飛MySql
- 重溫Java泛型,帶你更深入地理解它,更好的使用它!Java泛型
- 帶你理解Lock鎖原理
- [譯]帶你理解 Async/awaitAI
- 深入理解Java記憶體模型(七)——總結Java記憶體模型
- 阿里P8大佬帶你深入解析JVM與java阿里JVMJava
- 深入淺出Tomcat/4 - Tomcat容器Tomcat
- 老司機帶你深入理解 Laravel 中介軟體(全域性中介軟體)Laravel
- (圖解 HTTP)一篇文章帶你深入理解 IP、TCP 和 DNS圖解HTTPTCPDNS
- 一步一圖帶你深入理解 Linux 實體記憶體管理Linux記憶體
- 一條update語句到底加了多少鎖?帶你深入理解底層原理
- 3個框框帶你理解EventLoopOOP
- Android 自定義View:深入理解自定義屬性(七)AndroidView
- 學習Tomcat(七)之Spring內嵌TomcatTomcatSpring
- 帶你深入理解圖靈機--什麼是圖靈機、圖靈完備圖靈