Java?Servlet異步請(qǐng)求開(kāi)啟的簡(jiǎn)單步驟
1. 背景
在研究長(zhǎng)輪詢的實(shí)現(xiàn)過(guò)程,有使用到Servlet3的異步請(qǐng)求。下面就來(lái)學(xué)習(xí)一下Servlet3的異步請(qǐng)求
現(xiàn)在Servlet的版本已經(jīng)到了5
2. Servlet同步請(qǐng)求
以Tomcat服務(wù)器為例:
- Http請(qǐng)求到達(dá)Tomcat
- Tomcat從線程池中取出線程處理到達(dá)Tomcat的請(qǐng)求
- 將請(qǐng)求Http解析為HttpServletRequest
- 分發(fā)到具體Servlet處理對(duì)應(yīng)的業(yè)務(wù)
- 通過(guò)HttpServletResponse返回處理的數(shù)據(jù)

正常情況下請(qǐng)求模型和上面的模型一樣,所有的請(qǐng)求交給Tomcat服務(wù)器的線程池處理,整個(gè)動(dòng)作處理完成才釋放回線程池。
這里就存在了一個(gè)問(wèn)題如果后期的業(yè)務(wù)處理時(shí)間比較長(zhǎng)。那么處理請(qǐng)求的線程就會(huì)被一直占用。當(dāng)請(qǐng)求越來(lái)越多被占用的線程也會(huì)越來(lái)越多。直到被耗盡線程池中所有的線程。后續(xù)進(jìn)來(lái)的就一直被阻塞等待線程來(lái)處理。
當(dāng)用戶不關(guān)心提交的返回可以定義業(yè)務(wù)處理線程池,前端請(qǐng)求提交后,Tomcat線程將處理提交給業(yè)務(wù)線程池立即返回。Spring 中的異步任務(wù)(@Async)就是這樣的。
3. Servlet異步請(qǐng)求
同樣以Tomcat服務(wù)為例:
- 將請(qǐng)求Http解析為HttpServletRequest
- 分發(fā)到具體Servlet處理,將業(yè)務(wù)提交給自定義業(yè)務(wù)線程池,Tomcat線程立刻被釋放。
- 當(dāng)業(yè)務(wù)線程將任務(wù)執(zhí)行結(jié)束,將會(huì)將結(jié)果轉(zhuǎn)交給Tomcat線程池。
- 通過(guò)HttpServletResponse返回處理的數(shù)據(jù)
引入異步Servlet3整體流程:

使用異步 Servelt,Tomcat 線程僅僅處理請(qǐng)求解析動(dòng)作,所有耗時(shí)較長(zhǎng)的業(yè)務(wù)操作全部交給業(yè)務(wù)線程池,所以相比同步請(qǐng)求, Tomcat 線程可以處理 更多請(qǐng)求。雖然將業(yè)務(wù)交給了業(yè)務(wù)流程處理,但是前端還在等待結(jié)果返回(同步等待返回)。
異步處理,前端會(huì)同步等待結(jié)果返回。很多人會(huì)覺(jué)得異步請(qǐng)求會(huì)返回更快。其實(shí)不然由于異步存在線程的切換。所有返回時(shí)間會(huì)比同步的慢。
雖然沒(méi)有降低相應(yīng)時(shí)間但是還是有其他明顯的優(yōu)點(diǎn):
- 可以處理更高并發(fā)連接數(shù),提高系統(tǒng)整體吞吐量
- 請(qǐng)求解析與業(yè)務(wù)處理完全分離,職責(zé)單一
- 自定義業(yè)務(wù)線程池,我們可以更容易對(duì)其監(jiān)控,降級(jí)等處理
- 可以根據(jù)不同業(yè)務(wù),自定義不同線程池,相互隔離,不用互相影響
4. 異步Servlet使用方法
使用異步Servlet只需要三步:
- HttpServletRequest#startAsync() 獲取 AsyncContext 異步上下文
- 使用自定義業(yè)務(wù)線程池處理業(yè)務(wù)
- AsyncContext#getResponse() 返回處理結(jié)果給前端,然后調(diào)用 AsyncContext#complete()
5. Spring中的實(shí)現(xiàn)例子
代碼如下圖:

- 開(kāi)啟異步Servlet
- 模擬業(yè)務(wù)執(zhí)行
- 返回結(jié)果給前端
前面有說(shuō)過(guò)前端是一直在同步等待的我們通過(guò)運(yùn)行代碼來(lái)驗(yàn)證一下。結(jié)果如下圖:

附:異步對(duì)象監(jiān)聽(tīng)器
在異步對(duì)象完成、超時(shí)、錯(cuò)誤或者開(kāi)始時(shí)監(jiān)聽(tīng)
//獲取異步上下文對(duì)象
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異步請(qǐng)求開(kāi)啟的文章就介紹到這了,更多相關(guān)Servlet異步請(qǐng)求開(kāi)啟內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解
這篇文章主要為大家介紹了Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Java使用黑盒方式模擬實(shí)現(xiàn)內(nèi)網(wǎng)穿透
這篇文章主要介紹了Java使用黑盒方式模擬實(shí)現(xiàn)內(nèi)網(wǎng)穿透,內(nèi)網(wǎng)穿透,也即 NAT 穿透,進(jìn)行 NAT 穿透是為了使具有某一個(gè)特定源 IP 地址和源端口號(hào)的數(shù)據(jù)包不被 NAT 設(shè)備屏蔽而正確路由到內(nèi)網(wǎng)主機(jī),需要的朋友可以參考下2023-05-05
Java實(shí)現(xiàn)添加文字水印&圖片水印的方法詳解
為圖片添加水印的主要作用是保護(hù)圖片版權(quán),防止圖片被未經(jīng)授權(quán)的人使用或傳播。本文為大家介紹了Java實(shí)現(xiàn)添加文字水印&圖片水印的具體方法,需要的可以參考一下2023-02-02
SpringCloud聲明式Feign客戶端調(diào)用工具使用
這篇文章主要為大家介紹了SpringCloud聲明式Feign客戶端調(diào)用工具使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
SpringBoot如何整合Springsecurity實(shí)現(xiàn)數(shù)據(jù)庫(kù)登錄及權(quán)限控制
這篇文章主要給大家介紹了關(guān)于SpringBoot如何整合Springsecurity實(shí)現(xiàn)數(shù)據(jù)庫(kù)登錄及權(quán)限控制的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-01-01

