久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Tomcat服務器底層原理是什么

137次閱讀
沒有評論

共計 9366 個字符,預計需要花費 24 分鐘才能閱讀完成。

這篇文章主要介紹“Tomcat 服務器底層原理是什么”,在日常操作中,相信很多人在 Tomcat 服務器底層原理是什么問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Tomcat 服務器底層原理是什么”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!

Tomcat 是什么?

Tomcat 是開源的 Java Web 應用服務器,實現了 Java EE 的部分技術規范,比如 Java Servlet、Java Server  Page、JSTL、Java WebSocket。Java EE 是 Sun 公   司為企業級應用推出的標準平臺,定義了一系列用于企業級開發的技術規范。除了上述的之外,還有 EJB、Java Mail、JPA、JTA、JMS   等,而這些都依賴具體容器的實現。

上圖對比了 Java EE 容器的實現情況,Tomcat 和 Jetty 都只提供了 Java Web 容器必需的 Servlet 和 JSP   規范,開發者要想實現其他的功能,需要自己依賴其他開源實現。

Glassfish 是由 sun 公司推出,Java EE 最新規范出來之后,首先會在 Glassfish 上進行實現,所以是研究 Java EE   最新技術的首選。

最常見的情況是使用 Tomcat 作為 Java Web 服務器,使用 Spring   提供的開箱即用的強大功能,并依賴其他開源庫來完成負責的業務功能實現。

Servlet 容器

Tomcat 組成

如下圖所示,主要有 Container 和 Connector 以及相關組件構成。

Server:指的就是整個 Tomcat 服 務器,包含多組服務,負責管理和 啟動各個 Service,同時監聽 8005 端口發過來的 shutdown   命令,用 于關閉整個容器 ;

Service:Tomcat 封裝的、對外提 供完整的、基于組件的 web 服務,包含 Connectors、Container 兩個   核心組件,以及多個功能組件,各 個 Service 之間是獨立的,但是共享 同一 JVM 的資源 ;

Connector:Tomcat 與外部世界的連接器,監聽固定端口接收外部請求,傳遞給 Container,并 將 Container   處理的結果返回給外部

Container:Catalina,Servlet 容器,內部有多層容器組成,用于管理 Servlet 生命周期,調用 servlet 相關方法

Loader:封裝了 Java ClassLoader,用于 Container 加載類文件;Realm:Tomcat 中為 web   應用程序提供訪問認證和角色管理的機制;

JMX:Java SE 中定義技術規范,是一個為應用程序、設備、系統等植入管理功能的框架,通過 JMX 可以遠程監控 Tomcat 的運行狀態

Jasper:Tomcat 的 Jsp 解析引擎,用于將 Jsp 轉換成 Java 文件,并編譯成 class 文件。Session:負責管理和創建  session,以及 Session 的持久化(可自定義),支持 session 的集群。

Pipeline:在容器中充當管道的作用,管道中可以設置各種 valve(閥門),請求和響應在經由管   道中各個閥門處理,提供了一種靈活可配置的處理請求和響應的機制。

Naming:命名服務,JNDI,Java 命名和目錄接口,是一組在 Java 應用中訪問命名和目錄服務的  API。命名服務將名稱和對象聯系起來,使得我們可以用名稱訪問對象,目錄服務也是一種命名 服務,對象不但有名稱,還有屬性。Tomcat 中可以使用 JNDI   定義數據源、配置信息,用于開發 與部署的分離。

Container 組成

Engine:Servlet 的頂層容器,包含一 個或多個 Host 子容器;

Host:虛擬主機,負責 web 應用的部 署和 Context 的創建;

Context:Web 應用上下文,包含多個 Wrapper,負責 web 配置的解析、管 理所有的 Web 資源;

Wrapper:最底層的容器,是對 Servlet 的封裝,負責 Servlet 實例的創 建、執行和銷毀。

生命周期管理

Tomcat 為了方便管理組件和容器的生命周期,定義了從創建、啟動、到停止、銷毀共 12 種狀態。

tomcat   生命周期管理了內部狀態變化的規則控制,組件和容器只需實現相應的生命周期方法,即可完成各生命周期內的操作(initInternal、startInternal、stopInternal、 destroyInternal);

比如執行初始化操作時,會判斷當前狀態是否 New,如果不是則拋出生命周期異常; 是的話則設置當前狀態為 Initializing,并執行  initInternal 方法,由子類實現,方法執行成功則設置當前狀態為 Initialized,執行失敗則設置為 Failed 狀態;

Tomcat   的生命周期管理引入了事件機制,在組件或容器的生命周期狀態發生變化時會通知事件監聽器,監聽器通過判斷事件的類型來進行相應的操作。事件監聽器的添加可以在  server.xml 文件中進行配置;

Tomcat 各類容器的配置過程是通過添加 listener 的方式來進行的,從而達到配置邏輯與容器的解耦。如  EngineConfig、HostConfig、ContextConfig。

EngineConfig:主要打印啟動和停止日志

HostConfig:主要處理部署應用,解析應用 META-INF/context.xml 并創建應用

Context ContextConfig:主要解析并合并 web.xml,掃描應用的各類 web 資源  (filter、servlet、listener)

Tomcat 的啟動過程

啟動從 Tomcat 提供的 start.sh 腳本開始,shell 腳本會調用 Bootstrap 的 main 方法,實際調用了 Catalina   相應的 load、start 方法。

load 方法會通過 Digester 進行 config/server.xml 的解析,在解析的過程中會根據 xml 中的關系   和配置信息來創建容器,并設置相關的屬性。

接著 Catalina 會調用 StandardServer 的 init 和 start 方法進行容器的初始化和啟動。

按照 xml 的配置關系,server 的子元素是 service,service 的子元素是頂層容器  Engine,每層容器都持有自己的子容器,而這些元素都實現了生命周期管理的各個方法,因此就很容易的完成整個容器的啟動、關閉等生命周期的管理。

StandardServer 完成 init 和 start 方法調用后,會一直監聽來自 8005 端口(可配置)。

如果接收 到 shutdown 命令,則會退出循環監聽,執行后續的 stop 和 destroy 方法,完成 Tomcat 容器的關閉。

同時也會調用 JVM 的 Runtime.getRuntime()?.addShutdownHook 方法,在虛擬機意外退出的時候來關閉容器。

所有容器都是繼承自 ContainerBase,基類中封裝了容器中的重復工作,負責啟動容器相關的組件  Loader、Logger、Manager、Cluster、Pipeline,啟動子容器(線程池并發啟動子容器,通過線程池 submit 多個線程,調用后返回  Future 對象,線程內部啟動子容器,接著調用 Future 對象 的 get 方法來等待執行結果)。

List future  results = new ArrayList future  for (int i = 0; i   children.length; i++) { results.add(startStopExecutor.submit(new StartChild(children[i]))); } boolean fail = false; for (Futureresult :results) { try { result.get(); } catch (Exception e) { log.error(sm.getString( containerBase.threadedStartFailed), e); fail = true; } }

Web 應用的部署方式

注:catalina.home:安裝目錄;catalina.base:工作目錄; 默認值 user.dir

Server.xml 配置 Host 元素,指定 appBase 屬性,默認 \$catalina.base/webapps/

Server.xml 配置 Context 元素,指定 docBase,元素,指定 web 應用的路徑

自定義配置:在 \$catalina.base/EngineName/HostName/XXX.xml 配置 Context 元素

HostConfig 監聽了 StandardHost 容器的事件,在 start 方法中解析上述配置文件:

掃描 appbase 路徑下的所有文件夾和 war 包,解析各個應用的 META-INF/context.xml,并 創建  StandardContext,并將 Context 加入到 Host 的子容器中。

解析 $catalina.base/EngineName/HostName/ 下的所有 Context 配置,找到相應 web 應 用的位置,解析各個應用的  META-INF/context.xml,并創建 StandardContext,并將 Context 加入到 Host 的子容器中。

注:

HostConfig 并沒有實際解析 Context.xml,而是在 ContextConfig 中進行的。

HostConfig 中會定期檢查 watched 資源文件(context.xml 配置文件)

ContextConfig 解析 context.xml 順序:

先解析全局的配置 config/context.xml

然后解析 Host 的默認配置 EngineName/HostName/context.xml.default

最后解析應用的 META-INF/context.xml

ContextConfig 解析 web.xml 順序:

先解析全局的配置 config/web.xml

然后解析 Host 的默認配置 EngineName/HostName/web.xml.default 接著解析應用的  MEB-INF/web.xml

掃描應用 WEB-INF/lib/ 下的 jar 文件,解析其中的 META-INF/web-fragment.xml 最后合并 xml 封裝成  WebXml,并設置 Context

注:

掃描 web 應用和 jar 中的注解 (Filter、Listener、Servlet) 就是上述步驟中進行的。

容器的定期執行:backgroundProcess,由 ContainerBase 來實現的,并且只有在頂層容器   中才會開啟線程。(backgroundProcessorDelay=10 標志位來控制)

Servlet 生命周期

Servlet 是用 Java 編寫的服務器端程序,其主要功能在于交互式地瀏覽和修改數據,生成動態 Web 內容。

請求到達 server 端,server 根據 url 映射到相應的 Servlet

判斷 Servlet 實例是否存在,不存在則加載和實例化 Servlet 并調用 init 方法

Server 分別創建 Request 和 Response 對象,調用 Servlet 實例的 service 方法(service 方法 內部會根據  http 請求方法類型調用相應的 doXXX 方法)

doXXX 方法內為業務邏輯實現,從 Request 對象獲取請求參數,處理完畢之后將結果通過 response 對象返回給調用方

當 Server 不再需要 Servlet 時(一般當 Server 關閉時),Server 調用 Servlet 的 destroy() 方   法。

load on startup

當值為 0 或者大于 0 時,表示容器在應用啟動時就加載這個 servlet; 當是一個負數時或者沒有指定時,則指示容器在該 servlet   被選擇時才加載; 正數的值越小,啟動該 servlet 的優先級越高;

single thread model

每次訪問 servlet,新建 servlet 實體對象,但并不能保證線程安全,同時 tomcat 會限制 servlet 的實例數目。

請求處理過程

根據 server.xml 配置的指定的 connector 以及端口監聽 http、或者 ajp 請求

請求到來時建立連接, 解析請求參數, 創建 Request 和 Response 對象, 調用頂層容器 pipeline 的 invoke 方法

容器之間層層調用, 最終調用業務 servlet 的 service 方法

Connector 將 response 流中的數據寫到 socket 中

Pipeline 與 Valve

Pipeline 可以理解為現實中的管道,Valve 為管道中的閥門,Request 和 Response 對象在管道中   經過各個閥門的處理和控制。

每個容器的管道中都有一個必不可少的 basic valve, 其他的都是可選的,basic valve 在管道中最 后調用, 同時負責調用子容器的第一個  valve。

Valve 中主要的三個方法:setNext、getNext、invoke;valve 之間的關系是單向鏈式結構, 本身 invoke 方法中會調用下一個  valve 的 invoke 方法。

各層容器對應的 basic valve 分別是 StandardEngineValve、StandardHostValve、 StandardContextValve、StandardWrapperValve。

JSP 引擎

JSP 生命周期

編譯階段:servlet 容器編譯 servlet 源文

件, 生成 servlet 類

初始化階段: 加載與 JSP 對應的 servlet 類, 創建其實例, 并調用它的初始化方法

執行階段: 調用與 JSP 對應的 servlet 實例的 服務方法

銷毀階段: 調用與 JSP 對應的 servlet 實例的 銷毀方法, 然后銷毀 servlet 實例

JSP 元素

代碼片段:%

JSP 聲明:%! …=

JSP 表達式:%=

JSP 注釋:%–

JSP 指令:%@ directive= attribute=“value”

JSP 行為:

HTML 元素:html/head/body/div/p/ hellip;

JSP 隱式對象:request、response、out、session、application、config、pageContext、page、Exception

JSP 元素說明

代碼片段: 包含任意量的 Java 語句、變量、方法或表達式;

JSP 聲明: 一個聲明語句可以聲明一個或多個變量、方法, 供后面的 Java 代碼使用;

JSP 表達式: 輸出 Java 表達式的值,String 形式;

JSP 注釋: 為代碼作注釋以及將某段代碼注釋掉

JSP 指令: 用來設置與整個 JSP 頁面相關的屬性

%@ page= …= 定義頁面的依賴屬性, 比如 language、contentType、errorPage、isErrorPage、import、isThreadSafe、session 等等

%@ include= …= 包含其他的 JSP 文件、HTML 文件或文本文件, 是該 JSP 文件的一部分, 會被同時編譯執行

%@ taglib= …= 引入標簽庫的定義, 可以是自定義標簽

JSP 行為:jsp:include、jsp:useBean、jsp:setProperty、jsp:getProperty、jsp:forward

JSP 解析過程

Tomcat 服務器底層原理是什么

代碼片段: 在_jspService()方法內直接輸出

JSP 聲明: 在 servlet 類中進行輸出

JSP 表達式: 在_jspService()方法內直接輸出

JSP 注釋: 直接忽略, 不輸出

JSP 指令: 根據不同指令進行區分,include: 對引入的文件進行解析;page 相關的屬性會做為 JSP   的屬性, 影響的是解析和請求處理時的行為

JSP 行為: 不同的行為有不同的處理方式,jsp:useBean 為例, 會從 pageContext 根據 scope 的 類別獲取 bean   對象, 如果沒有會創建 bean, 同時存到相應 scope 的 pageContext 中

HTML: 在_jspService()方法內直接輸出

JSP 隱式對象: 在_jspService()方法會進行聲明, 只能在方法中使用;

Connector

Tomcat 服務器底層原理是什么

Http:HTTP 是超文本傳輸協議, 是客戶端瀏覽器或其他程序與 Web 服務器之間的應用層通信協議。

AJP:Apache JServ 協議 (AJP) 是一種二進制協議, 專門代理從 Web 服務器到位于后端的應用 程序服務器的入站請求。

阻塞 IO

Tomcat 服務器底層原理是什么

非阻塞 IO

Tomcat 服務器底層原理是什么

IO 多路復用

Tomcat 服務器底層原理是什么

阻塞與非阻塞的區別在于進行讀操作和寫操作的系統調用時,如果此時內核態沒有數據可讀或者沒有緩沖空間可寫時,是否阻塞。

IO 多路復用的好處在于可同時監聽多個 socket 的可讀和可寫事件,這樣就能使得應用可以同時監聽多個 socket,釋放了應用線程資源。

Tomcat 各類 Connector 對比

Tomcat 服務器底層原理是什么

Connector 的實現模式有三種,分別是 BIO、NIO、APR,可以在 server.xml 中指定。

JIO:用 java.io 編寫的 TCP 模塊,阻塞 IO

NIO:用 java.nio 編寫的 TCP 模塊,非阻塞 IO,(IO 多路復用)

APR:全稱 Apache Portable Runtime,使用 JNI 的方式來進行讀取文件以及進行網絡傳輸

Apache Portable Runtime 是一個高度可移植的庫,它是 Apache HTTP Server 2.x 的核心。

APR 具有許多用途,包括訪問高級 IO 功能 (如 sendfile,epoll 和 OpenSSL),操作系統級功能(隨機數生成,系統狀態等) 和本地進程處理(共享內存,NT 管道和 Unix 套接字)。

表格中字段含義說明:

Support Polling:是否支持基于 IO 多路復用的 socket 事件輪詢

Polling Size:輪詢的最大連接數

Wait for next  Request:在等待下一個請求時,處理線程是否釋放,BIO 是沒有釋放的,所以在 keep-alive=true 的情況下處理的并發連接數有限

Read Request Headers:由于 request header 數據較少,可以由容器提前解析完畢,不需要阻塞

Read Request Body:讀取 request body 的數據是應用業務邏輯的事情,同時 Servlet 的限制,是需要阻塞讀取的

Write Response:跟讀取 request body 的邏輯類似,同樣需要阻塞寫

NIO 處理相關類

Tomcat 服務器底層原理是什么

Acceptor 線程負責接收連接,調用 accept 方法阻塞接收建立的連接,并對 socket 進行封裝成 PollerEvent,指定注冊的事件為 op_read,并放入到 EventQueue 隊列中,PollerEvent 的 run 方法邏輯的是將 Selector 注冊到 socket 的指定事件;

Poller 線程從 EventQueue 獲取 PollerEvent,并執行 PollerEvent 的 run 方法,調用 Selector 的 select 方法,如果有可讀的 Socket 則創建 Http11NioProcessor,放入到線程池中執行;

CoyoteAdapter 是 Connector 到 Container 的適配器,Http11NioProcessor 調用其提供的 service 方法,內部創建 Request 和 Response 對象,并調用最頂層容器的 Pipeline 中的第一個 Valve 的 invoke 方法;

Mapper 主要處理 http url 到 servlet 的映射規則的解析,對外提供 map 方法。

NIO Connector 主要參數

Tomcat 服務器底層原理是什么

Comet

Comet 是一種用于 web 的推送技術,能使服務器實時地將更新的信息傳送到客戶端,而無須客戶端發出請求;

在 WebSocket 出來之前,如果不適用 comet,只能通過瀏覽器端輪詢 Server 來模擬實現服務器端推送;

Comet 支持 servlet 異步處理 IO,當連接上數據可讀時觸發事件,并異步寫數據(阻塞)。

Tomcat 服務器底層原理是什么

Tomcat 要實現 Comet,只需繼承 HttpServlet 同時,實現 CometProcessor 接口。

Begin:新的請求連接接入調用,可進行與 Request 和 Response 相關的對象初始化操作,并保存 response 對象,用于后續寫入數據

Read:請求連接有數據可讀時調用

End:當數據可用時,如果讀取到文件結束或者 response 被關閉時則被調用

Error:在連接上發生異常時調用,數據讀取異常、連接斷開、處理異常、socket 超時

Note:

Read:在 post 請求有數據,但在 begin 事件中沒有處理,則會調用 read,如果 read 沒有讀取數據,在會觸發 Error 回調,關閉 socket

End:當 socket 超時,并且 response 被關閉時也會調用;server 被關閉時調用

Error:除了 socket 超時不會關閉 socket,其他都會關閉 socket

End 和 Error 時間觸發時應關閉當前 comet 會話,即調用 CometEvent 的 close 方法

Note:在事件觸發時要做好線程安全的操作

異步 Servlet

Tomcat 服務器底層原理是什么

傳統流程:

首先,Servlet 接收到請求之后,request 數據解析;

接著,調用業務接口的某些方法,以完成業務處理;

最后,根據處理的結果提交響應,Servlet 線程結束。

Tomcat 服務器底層原理是什么

異步處理流程:

客戶端發送一個請求

Servlet 容器分配一個線程來處理容器中的一個 servlet

servlet 調用 request.startAsync(),保存 AsyncContext, 然后返回

任何方式存在的容器線程都將退出,但是 response 仍然保持開放

業務線程使用保存的 AsyncContext 來完成響應(線程池)

客戶端收到響應

Servlet 線程將請求轉交給一個異步線程來執行業務處理,線程本身返回至容器,此時 Servlet   還沒有生成響應數據,異步線程處理完業務以后,可以直接生成響應數據(異步線程擁有 ServletRequest 和 ServletResponse   對象的引用)。

為什么 web 應用中支持異步?

推出異步,主要是針對那些比較耗時的請求:比如一次緩慢的數據庫查詢,一次外部 REST API 調用,   或者是其他一些 I / O 密集型操作。這種耗時的請求會很快的耗光 Servlet 容器的線程池,繼而影響可擴展性。

Note:從客戶端的角度來看,request 仍然像任何其他的 HTTP 的 request-response 交互一樣,只是耗費了更長的時間而已。

異步事件監聽

onStartAsync:Request 調用 startAsync 方法時觸發

onComplete:syncContext 調用 complete 方法時觸發

onError:處理請求的過程出現異常時觸發

onTimeout:socket 超時觸發

Note :

onError/ onTimeout 觸發后,會緊接著回調 onComplete

onComplete 執行后,就不可再操作 request 和 response

到此,關于“Tomcat 服務器底層原理是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-03發表,共計9366字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 灌云县| 昌乐县| 都昌县| 库车县| 永清县| 仙游县| 富裕县| 德江县| 育儿| 云林县| 新闻| 宁国市| 涿鹿县| 南乐县| 连南| 霍城县| 蓬莱市| 天门市| 泸定县| 新泰市| 秦安县| 洛扎县| 安福县| 丰县| 安新县| 咸阳市| 顺义区| 博野县| 神池县| 双流县| 苏州市| 米易县| 台中市| 恩平市| 磴口县| 安康市| 汽车| 交口县| 阿合奇县| 北安市| 汶上县|