您好,登錄后才能下訂單哦!
這篇文章主要介紹“Tomcat服務(wù)器底層原理是什么”,在日常操作中,相信很多人在Tomcat服務(wù)器底層原理是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Tomcat服務(wù)器底層原理是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
Tomcat是什么?
Tomcat是開(kāi)源的 Java Web 應(yīng)用服務(wù)器,實(shí)現(xiàn)了 Java EE 的部分技術(shù)規(guī)范,比如 Java Servlet、Java Server Page、JSTL、Java WebSocket。Java EE 是 Sun 公 司為企業(yè)級(jí)應(yīng)用推出的標(biāo)準(zhǔn)平臺(tái),定義了一系列用于企業(yè)級(jí)開(kāi)發(fā)的技術(shù)規(guī)范。除了上述的之外,還有 EJB、Java Mail、JPA、JTA、JMS 等,而這些都依賴具體容器的實(shí)現(xiàn)。
上圖對(duì)比了 Java EE 容器的實(shí)現(xiàn)情況,Tomcat 和 Jetty 都只提供了 Java Web 容器必需的 Servlet 和 JSP 規(guī)范,開(kāi)發(fā)者要想實(shí)現(xiàn)其他的功能,需要自己依賴其他開(kāi)源實(shí)現(xiàn)。
Glassfish 是由 sun 公司推出,Java EE 最新規(guī)范出來(lái)之后,首先會(huì)在 Glassfish 上進(jìn)行實(shí)現(xiàn),所以是研究 Java EE 最新技術(shù)的首選。
最常見(jiàn)的情況是使用 Tomcat 作為 Java Web 服務(wù)器,使用 Spring 提供的開(kāi)箱即用的強(qiáng)大功能,并依賴其他開(kāi)源庫(kù)來(lái)完成負(fù)責(zé)的業(yè)務(wù)功能實(shí)現(xiàn)。
Servlet容器
Tomcat 組成
如下圖所示,主要有 Container 和 Connector 以及相關(guān)組件構(gòu)成。
Server:指的就是整個(gè) Tomcat 服 務(wù)器,包含多組服務(wù),負(fù)責(zé)管理和 啟動(dòng)各個(gè) Service,同時(shí)監(jiān)聽(tīng) 8005 端口發(fā)過(guò)來(lái)的 shutdown 命令,用 于關(guān)閉整個(gè)容器 ;
Service:Tomcat 封裝的、對(duì)外提 供完整的、基于組件的 web 服務(wù), 包含 Connectors、Container 兩個(gè) 核心組件,以及多個(gè)功能組件,各 個(gè) Service 之間是獨(dú)立的,但是共享 同一 JVM 的資源 ;
Connector:Tomcat 與外部世界的連接器,監(jiān)聽(tīng)固定端口接收外部請(qǐng)求,傳遞給 Container,并 將 Container 處理的結(jié)果返回給外部
Container:Catalina,Servlet 容器,內(nèi)部有多層容器組成,用于管理 Servlet 生命周期,調(diào)用 servlet 相關(guān)方法
Loader:封裝了 Java ClassLoader,用于 Container 加載類文件;Realm:Tomcat 中為 web 應(yīng)用程序提供訪問(wèn)認(rèn)證和角色管理的機(jī)制;
JMX:Java SE 中定義技術(shù)規(guī)范,是一個(gè)為應(yīng)用程序、設(shè)備、系統(tǒng)等植入管理功能的框架,通過(guò) JMX 可以遠(yuǎn)程監(jiān)控 Tomcat 的運(yùn)行狀態(tài)
Jasper:Tomcat 的 Jsp 解析引擎,用于將 Jsp 轉(zhuǎn)換成 Java 文件,并編譯成 class 文件。Session:負(fù)責(zé)管理和創(chuàng)建 session,以及 Session 的持久化(可自定義),支持 session 的集群。
Pipeline:在容器中充當(dāng)管道的作用,管道中可以設(shè)置各種 valve(閥門),請(qǐng)求和響應(yīng)在經(jīng)由管 道中各個(gè)閥門處理,提供了一種靈活可配置的處理請(qǐng)求和響應(yīng)的機(jī)制。
Naming:命名服務(wù),JNDI, Java 命名和目錄接口,是一組在 Java 應(yīng)用中訪問(wèn)命名和目錄服務(wù)的 API。命名服務(wù)將名稱和對(duì)象聯(lián)系起來(lái),使得我們可以用名稱訪問(wèn)對(duì)象,目錄服務(wù)也是一種命名 服務(wù),對(duì)象不但有名稱,還有屬性。Tomcat 中可以使用 JNDI 定義數(shù)據(jù)源、配置信息,用于開(kāi)發(fā) 與部署的分離。
Container組成
Engine:Servlet 的頂層容器,包含一 個(gè)或多個(gè) Host 子容器;
Host:虛擬主機(jī),負(fù)責(zé) web 應(yīng)用的部 署和 Context 的創(chuàng)建;
Context:Web 應(yīng)用上下文,包含多個(gè) Wrapper,負(fù)責(zé) web 配置的解析、管 理所有的 Web 資源;
Wrapper:最底層的容器,是對(duì) Servlet 的封裝,負(fù)責(zé) Servlet 實(shí)例的創(chuàng) 建、執(zhí)行和銷毀。
生命周期管理
Tomcat 為了方便管理組件和容器的生命周期,定義了從創(chuàng)建、啟動(dòng)、到停止、銷毀共 12 種狀態(tài)。
tomcat 生命周期管理了內(nèi)部狀態(tài)變化的規(guī)則控制,組件和容器只需實(shí)現(xiàn)相應(yīng)的生命周期方法,即可完成各生命周期內(nèi)的操作(initInternal、startInternal、stopInternal、 destroyInternal);
比如執(zhí)行初始化操作時(shí),會(huì)判斷當(dāng)前狀態(tài)是否 New,如果不是則拋出生命周期異常;是的話則設(shè)置當(dāng)前狀態(tài)為 Initializing,并執(zhí)行 initInternal 方法,由子類實(shí)現(xiàn),方法執(zhí)行成功則設(shè)置當(dāng)前狀態(tài)為 Initialized,執(zhí)行失敗則設(shè)置為 Failed 狀態(tài);
Tomcat 的生命周期管理引入了事件機(jī)制,在組件或容器的生命周期狀態(tài)發(fā)生變化時(shí)會(huì)通知事件監(jiān)聽(tīng)器,監(jiān)聽(tīng)器通過(guò)判斷事件的類型來(lái)進(jìn)行相應(yīng)的操作。事件監(jiān)聽(tīng)器的添加可以在 server.xml 文件中進(jìn)行配置;
Tomcat 各類容器的配置過(guò)程是通過(guò)添加 listener 的方式來(lái)進(jìn)行的,從而達(dá)到配置邏輯與容器的解耦。如 EngineConfig、HostConfig、ContextConfig。
EngineConfig:主要打印啟動(dòng)和停止日志
HostConfig:主要處理部署應(yīng)用,解析應(yīng)用 META-INF/context.xml 并創(chuàng)建應(yīng)用
Context ContextConfig:主要解析并合并 web.xml,掃描應(yīng)用的各類 web 資源 (filter、servlet、listener)
Tomcat 的啟動(dòng)過(guò)程
啟動(dòng)從 Tomcat 提供的 start.sh 腳本開(kāi)始,shell 腳本會(huì)調(diào)用 Bootstrap 的 main 方法,實(shí)際調(diào)用了 Catalina 相應(yīng)的 load、start 方法。
load 方法會(huì)通過(guò) Digester 進(jìn)行 config/server.xml 的解析,在解析的過(guò)程中會(huì)根據(jù) xml 中的關(guān)系 和配置信息來(lái)創(chuàng)建容器,并設(shè)置相關(guān)的屬性。
接著 Catalina 會(huì)調(diào)用 StandardServer 的 init 和 start 方法進(jìn)行容器的初始化和啟動(dòng)。
按照 xml 的配置關(guān)系,server 的子元素是 service,service 的子元素是頂層容器 Engine,每層容器都持有自己的子容器,而這些元素都實(shí)現(xiàn)了生命周期管理的各個(gè)方法,因此就很容易的完成整個(gè)容器的啟動(dòng)、關(guān)閉等生命周期的管理。
StandardServer 完成 init 和 start 方法調(diào)用后,會(huì)一直監(jiān)聽(tīng)來(lái)自 8005 端口(可配置)。
如果接收 到 shutdown 命令,則會(huì)退出循環(huán)監(jiān)聽(tīng),執(zhí)行后續(xù)的 stop 和 destroy 方法,完成 Tomcat 容器的關(guān)閉。
同時(shí)也會(huì)調(diào)用 JVM 的 Runtime.getRuntime()?.addShutdownHook 方法,在虛擬機(jī)意外退出的時(shí)候來(lái)關(guān)閉容器。
所有容器都是繼承自 ContainerBase,基類中封裝了容器中的重復(fù)工作,負(fù)責(zé)啟動(dòng)容器相關(guān)的組件 Loader、Logger、Manager、Cluster、Pipeline,啟動(dòng)子容器(線程池并發(fā)啟動(dòng)子容器,通過(guò)線程池 submit 多個(gè)線程,調(diào)用后返回 Future 對(duì)象,線程內(nèi)部啟動(dòng)子容器,接著調(diào)用 Future 對(duì)象 的 get 方法來(lái)等待執(zhí)行結(jié)果)。
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 應(yīng)用的部署方式
注:catalina.home:安裝目錄;catalina.base:工作目錄;默認(rèn)值 user.dir
Server.xml 配置 Host 元素,指定 appBase 屬性,默認(rèn)\$catalina.base/webapps/
Server.xml 配置 Context 元素,指定 docBase,元素,指定 web 應(yīng)用的路徑
自定義配置:在\$catalina.base/EngineName/HostName/XXX.xml 配置 Context 元素
HostConfig 監(jiān)聽(tīng)了 StandardHost 容器的事件,在 start 方法中解析上述配置文件:
掃描 appbase 路徑下的所有文件夾和 war 包,解析各個(gè)應(yīng)用的 META-INF/context.xml,并 創(chuàng)建 StandardContext,并將 Context 加入到 Host 的子容器中。
解析$catalina.base/EngineName/HostName/下的所有 Context 配置,找到相應(yīng) web 應(yīng) 用的位置,解析各個(gè)應(yīng)用的 META-INF/context.xml,并創(chuàng)建 StandardContext,并將 Context 加入到 Host 的子容器中。
注:
HostConfig 并沒(méi)有實(shí)際解析 Context.xml,而是在 ContextConfig 中進(jìn)行的。
HostConfig 中會(huì)定期檢查 watched 資源文件(context.xml 配置文件)
ContextConfig 解析 context.xml 順序:
先解析全局的配置 config/context.xml
然后解析 Host 的默認(rèn)配置 EngineName/HostName/context.xml.default
最后解析應(yīng)用的 META-INF/context.xml
ContextConfig 解析 web.xml 順序:
先解析全局的配置 config/web.xml
然后解析 Host 的默認(rèn)配置 EngineName/HostName/web.xml.default 接著解析應(yīng)用的 MEB-INF/web.xml
掃描應(yīng)用 WEB-INF/lib/下的 jar 文件,解析其中的 META-INF/web-fragment.xml 最后合并 xml 封裝成 WebXml,并設(shè)置 Context
注:
掃描 web 應(yīng)用和 jar 中的注解(Filter、Listener、Servlet)就是上述步驟中進(jìn)行的。
容器的定期執(zhí)行:backgroundProcess,由 ContainerBase 來(lái)實(shí)現(xiàn)的,并且只有在頂層容器 中才會(huì)開(kāi)啟線程。(backgroundProcessorDelay=10 標(biāo)志位來(lái)控制)
Servlet 生命周期
Servlet 是用 Java 編寫(xiě)的服務(wù)器端程序,其主要功能在于交互式地瀏覽和修改數(shù)據(jù),生成動(dòng)態(tài) Web 內(nèi)容。
請(qǐng)求到達(dá) server 端,server 根據(jù) url 映射到相應(yīng)的 Servlet
判斷 Servlet 實(shí)例是否存在,不存在則加載和實(shí)例化 Servlet 并調(diào)用 init 方法
Server 分別創(chuàng)建 Request 和 Response 對(duì)象,調(diào)用 Servlet 實(shí)例的 service 方法(service 方法 內(nèi)部會(huì)根據(jù) http 請(qǐng)求方法類型調(diào)用相應(yīng)的 doXXX 方法)
doXXX 方法內(nèi)為業(yè)務(wù)邏輯實(shí)現(xiàn),從 Request 對(duì)象獲取請(qǐng)求參數(shù),處理完畢之后將結(jié)果通過(guò) response 對(duì)象返回給調(diào)用方
當(dāng) Server 不再需要 Servlet 時(shí)(一般當(dāng) Server 關(guān)閉時(shí)),Server 調(diào)用 Servlet 的 destroy() 方 法。
load on startup
當(dāng)值為 0 或者大于 0 時(shí),表示容器在應(yīng)用啟動(dòng)時(shí)就加載這個(gè) servlet; 當(dāng)是一個(gè)負(fù)數(shù)時(shí)或者沒(méi)有指定時(shí),則指示容器在該 servlet 被選擇時(shí)才加載; 正數(shù)的值越小,啟動(dòng)該 servlet 的優(yōu)先級(jí)越高;
single thread model
每次訪問(wèn) servlet,新建 servlet 實(shí)體對(duì)象,但并不能保證線程安全,同時(shí) tomcat 會(huì)限制 servlet 的實(shí)例數(shù)目。
請(qǐng)求處理過(guò)程
根據(jù) server.xml 配置的指定的 connector 以及端口監(jiān)聽(tīng) http、或者 ajp 請(qǐng)求
請(qǐng)求到來(lái)時(shí)建立連接,解析請(qǐng)求參數(shù),創(chuàng)建 Request 和 Response 對(duì)象,調(diào)用頂層容器 pipeline 的 invoke 方法
容器之間層層調(diào)用,最終調(diào)用業(yè)務(wù) servlet 的 service 方法
Connector 將 response 流中的數(shù)據(jù)寫(xiě)到 socket 中
Pipeline 與 Valve
Pipeline 可以理解為現(xiàn)實(shí)中的管道,Valve 為管道中的閥門,Request 和 Response 對(duì)象在管道中 經(jīng)過(guò)各個(gè)閥門的處理和控制。
每個(gè)容器的管道中都有一個(gè)必不可少的 basic valve,其他的都是可選的,basic valve 在管道中最 后調(diào)用,同時(shí)負(fù)責(zé)調(diào)用子容器的第一個(gè) valve。
Valve 中主要的三個(gè)方法:setNext、getNext、invoke;valve 之間的關(guān)系是單向鏈?zhǔn)浇Y(jié)構(gòu),本身 invoke 方法中會(huì)調(diào)用下一個(gè) valve 的 invoke 方法。
各層容器對(duì)應(yīng)的 basic valve 分別是 StandardEngineValve、StandardHostValve、 StandardContextValve、StandardWrapperValve。
JSP引擎
JSP 生命周期
編譯階段:servlet 容器編譯 servlet 源文
件,生成 servlet 類
初始化階段:加載與 JSP 對(duì)應(yīng)的 servlet 類, 創(chuàng)建其實(shí)例,并調(diào)用它的初始化方法
執(zhí)行階段:調(diào)用與 JSP 對(duì)應(yīng)的 servlet 實(shí)例的 服務(wù)方法
銷毀階段:調(diào)用與 JSP 對(duì)應(yīng)的 servlet 實(shí)例的 銷毀方法,然后銷毀 servlet 實(shí)例
JSP元素
代碼片段:<%>
JSP聲明:<%! ...="">
JSP表達(dá)式:<%=>
JSP注釋:<%-->
JSP指令:<%@ directive="" attribute="“value”">
JSP行為:
HTML元素:html/head/body/div/p/…
JSP隱式對(duì)象:request、response、out、session、application、config、pageContext、page、Exception
JSP 元素說(shuō)明
代碼片段:包含任意量的 Java 語(yǔ)句、變量、方法或表達(dá)式;
JSP 聲明:一個(gè)聲明語(yǔ)句可以聲明一個(gè)或多個(gè)變量、方法,供后面的 Java 代碼使用;
JSP 表達(dá)式:輸出 Java 表達(dá)式的值,String 形式;
JSP 注釋:為代碼作注釋以及將某段代碼注釋掉
JSP 指令:用來(lái)設(shè)置與整個(gè) JSP 頁(yè)面相關(guān)的屬性
<%@ page="" ...="">定義頁(yè)面的依賴屬性,比如 language、contentType、errorPage、 isErrorPage、import、isThreadSafe、session 等等
<%@ include="" ...="">包含其他的 JSP 文件、HTML 文件或文本文件,是該 JSP 文件的一部分,會(huì)被同時(shí)編譯執(zhí)行
<%@ taglib="" ...="">引入標(biāo)簽庫(kù)的定義,可以是自定義標(biāo)簽
JSP 行為:jsp:include、jsp:useBean、jsp:setProperty、jsp:getProperty、jsp:forward
JSP 解析過(guò)程
代碼片段:在_jspService()方法內(nèi)直接輸出
JSP 聲明: 在 servlet 類中進(jìn)行輸出
JSP 表達(dá)式:在_jspService()方法內(nèi)直接輸出
JSP 注釋:直接忽略,不輸出
JSP 指令:根據(jù)不同指令進(jìn)行區(qū)分,include:對(duì)引入的文件進(jìn)行解析;page 相關(guān)的屬性會(huì)做為 JSP 的屬性,影響的是解析和請(qǐng)求處理時(shí)的行為
JSP 行為:不同的行為有不同的處理方式,jsp:useBean 為例,會(huì)從 pageContext 根據(jù) scope 的 類別獲取 bean 對(duì)象,如果沒(méi)有會(huì)創(chuàng)建 bean,同時(shí)存到相應(yīng) scope 的 pageContext 中
HTML:在_jspService()方法內(nèi)直接輸出
JSP 隱式對(duì)象:在_jspService()方法會(huì)進(jìn)行聲明,只能在方法中使用;
Connector
Http:HTTP 是超文本傳輸協(xié)議,是客戶端瀏覽器或其他程序與 Web 服務(wù)器之間的應(yīng)用層通信協(xié)議。
AJP:Apache JServ 協(xié)議(AJP)是一種二進(jìn)制協(xié)議,專門代理從 Web 服務(wù)器到位于后端的應(yīng)用 程序服務(wù)器的入站請(qǐng)求。
阻塞 IO
非阻塞 IO
IO多路復(fù)用
阻塞與非阻塞的區(qū)別在于進(jìn)行讀操作和寫(xiě)操作的系統(tǒng)調(diào)用時(shí),如果此時(shí)內(nèi)核態(tài)沒(méi)有數(shù)據(jù)可讀或者沒(méi)有緩沖空間可寫(xiě)時(shí),是否阻塞。
IO多路復(fù)用的好處在于可同時(shí)監(jiān)聽(tīng)多個(gè)socket的可讀和可寫(xiě)事件,這樣就能使得應(yīng)用可以同時(shí)監(jiān)聽(tīng)多個(gè)socket,釋放了應(yīng)用線程資源。
Tomcat各類Connector對(duì)比
Connector的實(shí)現(xiàn)模式有三種,分別是BIO、NIO、APR,可以在server.xml中指定。
JIO:用java.io編寫(xiě)的TCP模塊,阻塞IO
NIO:用java.nio編寫(xiě)的TCP模塊,非阻塞IO,(IO多路復(fù)用)
APR:全稱Apache Portable Runtime,使用JNI的方式來(lái)進(jìn)行讀取文件以及進(jìn)行網(wǎng)絡(luò)傳輸
Apache Portable Runtime是一個(gè)高度可移植的庫(kù),它是Apache HTTP Server 2.x的核心。
APR具有許多用途,包括訪問(wèn)高級(jí)IO功能(如sendfile,epoll和OpenSSL),操作系統(tǒng)級(jí)功能(隨機(jī)數(shù)生成,系統(tǒng)狀態(tài)等)和本地進(jìn)程處理(共享內(nèi)存,NT管道和Unix套接字)。
表格中字段含義說(shuō)明:
Support Polling:是否支持基于IO多路復(fù)用的socket事件輪詢
Polling Size:輪詢的最大連接數(shù)
Wait for next Request:在等待下一個(gè)請(qǐng)求時(shí),處理線程是否釋放,BIO是沒(méi)有釋放的,所以在keep-alive=true的情況下處理的并發(fā)連接數(shù)有限
Read Request Headers:由于request header數(shù)據(jù)較少,可以由容器提前解析完畢,不需要阻塞
Read Request Body:讀取request body的數(shù)據(jù)是應(yīng)用業(yè)務(wù)邏輯的事情,同時(shí)Servlet的限制,是需要阻塞讀取的
Write Response:跟讀取request body的邏輯類似,同樣需要阻塞寫(xiě)
NIO處理相關(guān)類
Acceptor線程負(fù)責(zé)接收連接,調(diào)用accept方法阻塞接收建立的連接,并對(duì)socket進(jìn)行封裝成PollerEvent,指定注冊(cè)的事件為op_read,并放入到EventQueue隊(duì)列中,PollerEvent的run方法邏輯的是將Selector注冊(cè)到socket的指定事件;
Poller線程從EventQueue獲取PollerEvent,并執(zhí)行PollerEvent的run方法,調(diào)用Selector的select方法,如果有可讀的Socket則創(chuàng)建Http11NioProcessor,放入到線程池中執(zhí)行;
CoyoteAdapter是Connector到Container的適配器,Http11NioProcessor調(diào)用其提供的service方法,內(nèi)部創(chuàng)建Request和Response對(duì)象,并調(diào)用最頂層容器的Pipeline中的第一個(gè)Valve的invoke方法;
Mapper主要處理http url 到servlet的映射規(guī)則的解析,對(duì)外提供map方法。
NIO Connector主要參數(shù)
Comet
Comet是一種用于web的推送技術(shù),能使服務(wù)器實(shí)時(shí)地將更新的信息傳送到客戶端,而無(wú)須客戶端發(fā)出請(qǐng)求;
在WebSocket出來(lái)之前,如果不適用comet,只能通過(guò)瀏覽器端輪詢Server來(lái)模擬實(shí)現(xiàn)服務(wù)器端推送;
Comet支持servlet異步處理IO,當(dāng)連接上數(shù)據(jù)可讀時(shí)觸發(fā)事件,并異步寫(xiě)數(shù)據(jù)(阻塞)。
Tomcat要實(shí)現(xiàn)Comet,只需繼承HttpServlet同時(shí),實(shí)現(xiàn)CometProcessor接口。
Begin:新的請(qǐng)求連接接入調(diào)用,可進(jìn)行與Request和Response相關(guān)的對(duì)象初始化操作,并保存response對(duì)象,用于后續(xù)寫(xiě)入數(shù)據(jù)
Read:請(qǐng)求連接有數(shù)據(jù)可讀時(shí)調(diào)用
End:當(dāng)數(shù)據(jù)可用時(shí),如果讀取到文件結(jié)束或者response被關(guān)閉時(shí)則被調(diào)用
Error:在連接上發(fā)生異常時(shí)調(diào)用,數(shù)據(jù)讀取異常、連接斷開(kāi)、處理異常、socket超時(shí)
Note:
Read:在post請(qǐng)求有數(shù)據(jù),但在begin事件中沒(méi)有處理,則會(huì)調(diào)用read,如果read沒(méi)有讀取數(shù)據(jù),在會(huì)觸發(fā)Error回調(diào),關(guān)閉socket
End:當(dāng)socket超時(shí),并且response被關(guān)閉時(shí)也會(huì)調(diào)用;server被關(guān)閉時(shí)調(diào)用
Error:除了socket超時(shí)不會(huì)關(guān)閉socket,其他都會(huì)關(guān)閉socket
End和Error時(shí)間觸發(fā)時(shí)應(yīng)關(guān)閉當(dāng)前comet會(huì)話,即調(diào)用CometEvent的close方法
Note:在事件觸發(fā)時(shí)要做好線程安全的操作
異步Servlet
傳統(tǒng)流程:
首先,Servlet 接收到請(qǐng)求之后,request數(shù)據(jù)解析;
接著,調(diào)用業(yè)務(wù)接口的某些方法,以完成業(yè)務(wù)處理;
最后,根據(jù)處理的結(jié)果提交響應(yīng),Servlet 線程結(jié)束。
異步處理流程:
客戶端發(fā)送一個(gè)請(qǐng)求
Servlet容器分配一個(gè)線程來(lái)處理容器中的一個(gè)servlet
servlet調(diào)用request.startAsync(),保存AsyncContext, 然后返回
任何方式存在的容器線程都將退出,但是response仍然保持開(kāi)放
業(yè)務(wù)線程使用保存的AsyncContext來(lái)完成響應(yīng)(線程池)
客戶端收到響應(yīng)
Servlet 線程將請(qǐng)求轉(zhuǎn)交給一個(gè)異步線程來(lái)執(zhí)行業(yè)務(wù)處理,線程本身返回至容器,此時(shí) Servlet 還沒(méi)有生成響應(yīng)數(shù)據(jù),異步線程處理完業(yè)務(wù)以后,可以直接生成響應(yīng)數(shù)據(jù)(異步線程擁有 ServletRequest 和 ServletResponse 對(duì)象的引用)。
為什么web應(yīng)用中支持異步?
推出異步,主要是針對(duì)那些比較耗時(shí)的請(qǐng)求:比如一次緩慢的數(shù)據(jù)庫(kù)查詢,一次外部REST API調(diào)用, 或者是其他一些I/O密集型操作。這種耗時(shí)的請(qǐng)求會(huì)很快的耗光Servlet容器的線程池,繼而影響可擴(kuò)展性。
Note:從客戶端的角度來(lái)看,request仍然像任何其他的HTTP的request-response交互一樣,只是耗費(fèi)了更長(zhǎng)的時(shí)間而已。
異步事件監(jiān)聽(tīng)
onStartAsync:Request調(diào)用startAsync方法時(shí)觸發(fā)
onComplete:syncContext調(diào)用complete方法時(shí)觸發(fā)
onError:處理請(qǐng)求的過(guò)程出現(xiàn)異常時(shí)觸發(fā)
onTimeout:socket超時(shí)觸發(fā)
Note :
onError/ onTimeout觸發(fā)后,會(huì)緊接著回調(diào)onComplete
onComplete 執(zhí)行后,就不可再操作request和response
到此,關(guān)于“Tomcat服務(wù)器底層原理是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。