Java?Servlet異步請求開啟的簡單步驟
1. 背景
在研究長輪詢的實現(xiàn)過程,有使用到Servlet3的異步請求。下面就來學(xué)習(xí)一下Servlet3的異步請求
現(xiàn)在Servlet的版本已經(jīng)到了5
2. Servlet同步請求
以Tomcat服務(wù)器為例:
- Http請求到達(dá)Tomcat
- Tomcat從線程池中取出線程處理到達(dá)Tomcat的請求
- 將請求Http解析為HttpServletRequest
- 分發(fā)到具體Servlet處理對應(yīng)的業(yè)務(wù)
- 通過HttpServletResponse返回處理的數(shù)據(jù)
正常情況下請求模型和上面的模型一樣,所有的請求交給Tomcat服務(wù)器的線程池處理,整個動作處理完成才釋放回線程池。
這里就存在了一個問題如果后期的業(yè)務(wù)處理時間比較長。那么處理請求的線程就會被一直占用。當(dāng)請求越來越多被占用的線程也會越來越多。直到被耗盡線程池中所有的線程。后續(xù)進(jìn)來的就一直被阻塞等待線程來處理。
當(dāng)用戶不關(guān)心提交的返回可以定義業(yè)務(wù)處理線程池,前端請求提交后,Tomcat線程將處理提交給業(yè)務(wù)線程池立即返回。Spring 中的異步任務(wù)(@Async)就是這樣的。
3. Servlet異步請求
同樣以Tomcat服務(wù)為例:
- 將請求Http解析為HttpServletRequest
- 分發(fā)到具體Servlet處理,將業(yè)務(wù)提交給自定義業(yè)務(wù)線程池,Tomcat線程立刻被釋放。
- 當(dāng)業(yè)務(wù)線程將任務(wù)執(zhí)行結(jié)束,將會將結(jié)果轉(zhuǎn)交給Tomcat線程池。
- 通過HttpServletResponse返回處理的數(shù)據(jù)
引入異步Servlet3整體流程:
使用異步 Servelt,Tomcat 線程僅僅處理請求解析動作,所有耗時較長的業(yè)務(wù)操作全部交給業(yè)務(wù)線程池,所以相比同步請求, Tomcat 線程可以處理 更多請求。雖然將業(yè)務(wù)交給了業(yè)務(wù)流程處理,但是前端還在等待結(jié)果返回(同步等待返回)。
異步處理,前端會同步等待結(jié)果返回。很多人會覺得異步請求會返回更快。其實不然由于異步存在線程的切換。所有返回時間會比同步的慢。
雖然沒有降低相應(yīng)時間但是還是有其他明顯的優(yōu)點:
- 可以處理更高并發(fā)連接數(shù),提高系統(tǒng)整體吞吐量
- 請求解析與業(yè)務(wù)處理完全分離,職責(zé)單一
- 自定義業(yè)務(wù)線程池,我們可以更容易對其監(jiān)控,降級等處理
- 可以根據(jù)不同業(yè)務(wù),自定義不同線程池,相互隔離,不用互相影響
4. 異步Servlet使用方法
使用異步Servlet只需要三步:
- HttpServletRequest#startAsync() 獲取 AsyncContext 異步上下文
- 使用自定義業(yè)務(wù)線程池處理業(yè)務(wù)
- AsyncContext#getResponse() 返回處理結(jié)果給前端,然后調(diào)用 AsyncContext#complete()
5. Spring中的實現(xiàn)例子
代碼如下圖:
- 開啟異步Servlet
- 模擬業(yè)務(wù)執(zhí)行
- 返回結(jié)果給前端
前面有說過前端是一直在同步等待的我們通過運(yùn)行代碼來驗證一下。結(jié)果如下圖:
附:異步對象監(jiān)聽器
在異步對象完成、超時、錯誤或者開始時監(jiān)聽
//獲取異步上下文對象 AsyncContext ac=req.startAsync(); ac.addListener(new AsyncListener() { @Override public void onComplete(AsyncEvent asyncEvent) throws IOException { } @Override public void onTimeout(AsyncEvent asyncEvent) throws IOException { } @Override public void onError(AsyncEvent asyncEvent) throws IOException { } @Override public void onStartAsync(AsyncEvent asyncEvent) throws IOException { } });
總結(jié)
到此這篇關(guān)于Java Servlet異步請求開啟的文章就介紹到這了,更多相關(guān)Servlet異步請求開啟內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot2.X整合Spring-Cache緩存開發(fā)的實現(xiàn)
本文主要介紹了SpringBoot2.X整合Spring-Cache緩存開發(fā)的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Java SE使用數(shù)組實現(xiàn)高速數(shù)字轉(zhuǎn)換功能
隨著大數(shù)據(jù)時代的到來,數(shù)字轉(zhuǎn)換功能變得越來越重要,在Java開發(fā)中,數(shù)字轉(zhuǎn)換功能也是經(jīng)常用到的,下面我們就來學(xué)習(xí)一下如何使用Java SE數(shù)組實現(xiàn)高速的數(shù)字轉(zhuǎn)換功能吧2023-11-11Java獲取項目路徑方式System.getProperty(“user.dir“)
這篇文章主要介紹了Java獲取項目路徑方式System.getProperty(“user.dir“),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12shiro與spring?security用自定義異常處理401錯誤
這篇文章主要介紹了shiro與spring?security用自定義異常處理401錯誤,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11JAVA WEB中Servlet和Servlet容器的區(qū)別
這篇文章主要介紹了JAVA WEB中Servlet和Servlet容器的區(qū)別,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下2020-06-06