柚子快報激活碼778899分享:java Tomcat架構(gòu)理解
柚子快報激活碼778899分享:java Tomcat架構(gòu)理解
目錄
Tomcat架構(gòu)分析概要核心功能架構(gòu)組成核心組件組件層級Tomcat設(shè)計原則Connector三個功能 - 高內(nèi)聚低耦合EndPointProcessorAdapter - 適配器模式父子容器 - 組合模式Pipeline-Valve - 責任鏈模式Valve接口設(shè)計Pipline接口設(shè)計Tomcat生命周期狀態(tài)枚舉生命周期類圖
Tomcat架構(gòu)分析
概要
Java Servlet容器(Web服務(wù)器):Http服務(wù)器+Servlet容器
三種部署路徑(server.xml配置):webapps(Host)、絕對路徑(Context)、Catalina\localhost(Tomcat9)
核心功能
處理Socket連接,負責網(wǎng)絡(luò)字節(jié)流與Request和Response對象轉(zhuǎn)化加載管理Servlet處理Request
架構(gòu)組成
Connector:Tomcat的連接器,用于接收請求并將其發(fā)送給容器。Container:Tomcat的容器,負責管理Servlet、JSP和靜態(tài)資源的生命周期。Engine:Tomcat的引擎,管理容器的生命周期和分配請求。Host:Tomcat的主機,可以管理多個Web應(yīng)用程序。Context:Tomcat的上下文,用于管理單個Web應(yīng)用程序的配置信息。Servlet:Tomcat的Servlet,負責處理請求并生成響應(yīng)。JSP:Tomcat的JSP,用于動態(tài)生成Web內(nèi)容。
核心組件
Service -> Connetor綁定端口 -> Engine容器轉(zhuǎn)發(fā) -> Host虛擬主機 -> Context應(yīng)用 -> Wrapper(Servlet)邏輯處理
Server 組件:指的就是整個 Tomcat 服務(wù)器,包含多組服務(wù)(Service),負責管理和啟動各個Service,同時監(jiān)聽 8005 端口發(fā)過來的 shutdown 命令,用于關(guān)閉整個容器 。
Service組件:每個 Service 組件都包含了若干用于接收客戶端消息的 Connector 組件和處理請求的 Engine 組件。 Service 組件還包含了若干 Executor 組件,每個 Executor 都是一個線程池,它可以為 Service 內(nèi)所有組件提供線程池執(zhí)行任務(wù)。 Tomcat 內(nèi)可能有多個 Service,這樣的設(shè)計也是出于靈活性的考慮。通過在 Tomcat 中配置多個 Service,可以實現(xiàn)通過不同的端口號來訪問同一臺機器上部署的不同應(yīng)用。
連接器Connector組件:Tomcat 與外部世界的連接器,監(jiān)聽固定端口接收外部請求,傳遞給 Container,并將Container 處理的結(jié)果返回給外部。連接器對 Servlet 容器屏蔽了不同的應(yīng)用層協(xié)議及 I/O 模型,無論是 HTTP 還是 AJP,在容器中獲取到的都是一個標準的 ServletRequest 對象。
連接器需要實現(xiàn)的功能:
監(jiān)聽網(wǎng)絡(luò)端口。接受網(wǎng)絡(luò)連接請求。讀取請求網(wǎng)絡(luò)字節(jié)流。根據(jù)具體應(yīng)用層協(xié)議(HTTP/AJP)解析字節(jié)流,生成統(tǒng)一的 Tomcat Request 對象。將 Tomcat Request 對象轉(zhuǎn)成標準的 ServletRequest。調(diào)用 Servlet 容器,得到 ServletResponse。將 ServletResponse 轉(zhuǎn)成 Tomcat Response 對象。將 Tomcat Response 轉(zhuǎn)成網(wǎng)絡(luò)字節(jié)流。將響應(yīng)字節(jié)流寫回給瀏覽器。
容器Container組件:容器,顧名思義就是用來裝載東西的器具,在 Tomcat 里,容器就是用來裝載 Servlet 的。Tomcat 通過一種分層的架構(gòu),使得 Servlet 容器具有很好的靈活性。Tomcat 設(shè)計了 4 種容器,分別是 Engine、Host、Context 和 Wrapper。這 4 種容器不是平行關(guān)系,而是父子關(guān)系。
Engine:引擎,Servlet 的頂層容器,用來管理多個虛擬站點,一個 Service 最多只能有一個 Engine;Host:虛擬主機,負責 web 應(yīng)用的部署和 Context 的創(chuàng)建。可以給 Tomcat 配置多個虛擬主機地址,而一個虛擬主機下可以部署多個 Web 應(yīng)用程序;Context:Web 應(yīng)用上下文,包含多個 Wrapper,負責 web 配置的解析、管理所有的 Web 資源。一個Context對應(yīng)一個 Web 應(yīng)用程序。Wrapper:表示一個 Servlet,最底層的容器,是對 Servlet 的封裝,負責 Servlet 實例的創(chuàng)建、執(zhí)行和銷毀。
組件層級
Tomcat啟動期間會通過解析 server.xml,利用反射創(chuàng)建相應(yīng)的組件,所以xml中的標簽和源碼一一對應(yīng)。
Tomcat設(shè)計原則
設(shè)計復雜系統(tǒng)的基本思路:
首先要分析需求,根據(jù)高內(nèi)聚低耦合的原則確定子模塊,然后找出子模塊中的變化點和不變點,用接口和抽象基類去封裝不變點,在抽象基類中定義模板方法,讓子類自行實現(xiàn)抽象方法,也就是具體子類去實現(xiàn)變化點。
Connector三個功能 - 高內(nèi)聚低耦合
網(wǎng)絡(luò)通信。應(yīng)用層協(xié)議解析。Tomcat Request/Response 與 ServletRequest/ServletResponse 的轉(zhuǎn)化。
三個組件來實現(xiàn):EndPoint、Processor、Adapter
EndPoint 負責提供字節(jié)流給 Processor;Processor 負責提供 Tomcat Request 對象給 Adapter;Adapter 負責提供 ServletRequest 對象給容器。
EndPoint
EndPoint 是通信端點,即通信監(jiān)聽的接口,是具體的 Socket 接收和發(fā)送處理器,是對傳輸層的抽象,因此 EndPoint 是用來實現(xiàn) TCP/IP 協(xié)議的。
EndPoint 是一個接口,對應(yīng)的抽象實現(xiàn)類是 AbstractEndpoint,而 AbstractEndpoint 的具體子類,比如在 NioEndpoint 和 Nio2Endpoint 中,有兩個重要的子組件:Acceptor 和 SocketProcessor。其中 Acceptor 用于監(jiān)聽 Socket 連接請求。SocketProcessor 用于處理接收到的 Socket 請求,它實現(xiàn) Runnable 接口,在 Run 方法里調(diào)用協(xié)議處理組件 Processor 進行處理。為了提高處理能力,SocketProcessor 被提交到線程池來執(zhí)行,而這個線程池叫作執(zhí)行器(Executor)。
Processor
? Processor 用來實現(xiàn) HTTP/AJP 協(xié)議,Processor 接收來自 EndPoint 的 Socket,讀取字節(jié)流解析成 Tomcat Request 和 Response 對象,并通過 Adapter 將其提交到容器處理,Processor 是對應(yīng)用層協(xié)議的抽象。
Processor 是一個接口,定義了請求的處理等方法。它的抽象實現(xiàn)類 AbstractProcessor 對一些協(xié)議共有的屬性進行封裝,沒有對方法進行實現(xiàn)。具體的實現(xiàn)有 AJPProcessor、HTTP11Processor 等,這些具體實現(xiàn)類實現(xiàn)了特定協(xié)議的解析方法和請求處理方式。
EndPoint 接收到 Socket 連接后,生成一個 SocketProcessor 任務(wù)提交到線程池去處理,SocketProcessor 的 Run 方法會調(diào)用 Processor 組件去解析應(yīng)用層協(xié)議,Processor 通過解析生成 Request 對象后,會調(diào)用 Adapter 的 Service 方法。
Adapter - 適配器模式
由于協(xié)議不同,客戶端發(fā)過來的請求信息也不盡相同,Tomcat 定義了自己的 Request 類來“存放”這些請求信息。ProtocolHandler 接口負責解析請求并生成 Tomcat Request 類。但是這個 Request 對象不是標準的 ServletRequest,也就意味著,不能用 Tomcat Request 作為參數(shù)來調(diào)用容器。Tomcat 設(shè)計者的解決方案是引入 CoyoteAdapter,這是適配器模式的經(jīng)典運用(TomcatRequest到ServletRequest對象轉(zhuǎn)化使用適配器模式),連接器調(diào)用 CoyoteAdapter 的 Sevice 方法,傳入的是 Tomcat Request 對象,CoyoteAdapter 負責將 Tomcat Request 轉(zhuǎn)成 ServletRequest,再調(diào)用容器的 Service 方法。
父子容器 - 組合模式
Tomcat 設(shè)計了 4 種容器,分別是 Engine、Host、Context、Wrapper
Tomcat 采用組合模式來管理這些容器。具體實現(xiàn)方法是,所有容器組件都實現(xiàn)了 Container 接口,因此組合模式可以使得用戶對單容器對象和組合容器對象的使用具有一致性。
Container 接口定義如下:
public interface Container extends Lifecycle {
public void setName(String name);
public Container getParent();
public void setParent(Container container);
public void addChild(Container child);
public void removeChild(Container child);
public Container findChild(String name);
}
Pipeline-Valve - 責任鏈模式
連接器中的 Adapter 會調(diào)用容器的 Service 方法來執(zhí)行 Servlet,最先拿到請求的是 Engine 容器,Engine 容器對請求做一些處理后,會把請求傳給自己子容器 Host 繼續(xù)處理,依次類推,最后這個請求會傳給 Wrapper 容器,Wrapper 會調(diào)用最終的 Servlet 來處理。那么這個調(diào)用過程具體是怎么實現(xiàn)的呢?答案是使用 Pipeline-Valve 管道。
Pipeline-Valve 是責任鏈模式,責任鏈模式是指在一個請求處理的過程中有很多處理者依次對請求進行處理,每個處理者負責做自己相應(yīng)的處理,處理完之后將再調(diào)用下一個處理者繼續(xù)處理。
Valve接口設(shè)計
理解它的設(shè)計,第一步就是閥門設(shè)計。Valve 表示一個處理點,比如權(quán)限認證和記錄日志。
public interface Valve {
public Valve getNext();
public void setNext(Valve valve);
public void invoke(Request request, Response response) throws IOException, ServletException;
}
Pipline接口設(shè)計
由于Pipline是為容器設(shè)計的,所以它在設(shè)計時加入了一個Contained接口, 就是為了制定當前Pipline所屬的容器
public interface Pipeline extends Contained {
// 基礎(chǔ)的處理閥
public Valve getBasic();
public void setBasic(Valve valve);
// 對節(jié)點(閥門)增刪查
public void addValve(Valve valve);
public Valve[] getValves();
public void removeValve(Valve valve);
// 獲取第一個節(jié)點,遍歷的起點,所以需要有這方法
public Valve getFirst();
// 是否所有節(jié)點(閥門)都支持處理Servlet3異步處理
public boolean isAsyncSupported();
// 找到所有不支持Servlet3異步處理的閥門
public void findNonAsyncValves(Set
}
Pipeline 中維護了 Valve 鏈表,Valve 可以插入到 Pipeline 中,對請求做某些處理。整個調(diào)用鏈的觸發(fā)是 Valve 來完成的,Valve 完成自己的處理后,調(diào)用 getNext.invoke() 來觸發(fā)下一個 Valve 調(diào)用。每一個容器都有一個 Pipeline 對象,只要觸發(fā)這個 Pipeline 的第一個 Valve,這個容器里 Pipeline 中的 Valve 就都會被調(diào)用到。Basic Valve 處于 Valve 鏈表的末端,它是 Pipeline 中必不可少的一個 Valve,負責調(diào)用下層容器的 Pipeline 里的第一個 Valve。
整個調(diào)用過程由連接器中的 Adapter 觸發(fā)的,它會調(diào)用 Engine 的第一個 Valve:
//org.apache.catalina.connector.CoyoteAdapter#service
// Calling the container
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
Wrapper 容器的最后一個 Valve 會創(chuàng)建一個 Filter 鏈,并調(diào)用 doFilter() 方法,最終會調(diào)到 Servlet 的 service 方法。
//org.apache.catalina.core.StandardWrapperValve#invoke
filterChain.doFilter(request.getRequest(), response.getResponse());
Valve 和 Filter?的區(qū)別:
Valve 是 Tomcat 的私有機制,與 Tomcat 的基礎(chǔ)架構(gòu) /API 是緊耦合的。Servlet API 是公有的標準,所有的 Web 容器包括 Jetty 都支持 Filter 機制。?Valve 工作在 Web 容器級別,攔截所有應(yīng)用的請求;而 Servlet Filter 工作在應(yīng)用級別,只能攔截某個 Web 應(yīng)用的所有請求。
Tomcat生命周期
Tomcat生命周期包含組件的創(chuàng)建、初始化、啟動、停止和銷毀,通過LifeCycle 接口定義方法:init()、start()、stop() 和 destroy()
public interface Lifecycle {
/** 第1類:針對監(jiān)聽器 **/
// 添加監(jiān)聽器
public void addLifecycleListener(LifecycleListener listener);
// 獲取所有監(jiān)聽器
public LifecycleListener[] findLifecycleListeners();
// 移除某個監(jiān)聽器
public void removeLifecycleListener(LifecycleListener listener);
/** 第2類:針對控制流程 **/
// 初始化方法
public void init() throws LifecycleException;
// 啟動方法
public void start() throws LifecycleException;
// 停止方法,和start對應(yīng)
public void stop() throws LifecycleException;
// 銷毀方法,和init對應(yīng)
public void destroy() throws LifecycleException;
/** 第3類:針對狀態(tài) **/
// 獲取生命周期狀態(tài)
public LifecycleState getState();
// 獲取字符串類型的生命周期狀態(tài)
public String getStateName();
}
狀態(tài)枚舉
生命周期類圖
StandardServer、StandardService 是 Server 和 Service 組件的具體實現(xiàn)類,它們都繼承了 LifeCycleBase。StandardEngine、StandardHost、StandardContext 和 StandardWrapper 是相應(yīng)容器組件的具體實現(xiàn)類,因為它們都是容器,所以繼承了 ContainerBase 抽象基類,而 ContainerBase 實現(xiàn)了 Container 接口,也繼承了 LifeCycleBase 類,它們的生命周期管理接口和功能接口是分開的,這也符合設(shè)計中接口分離的原則。
柚子快報激活碼778899分享:java Tomcat架構(gòu)理解
文章鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。