SpringBoot異步請求


何為異步請求

在Servlet 3.0之前,Servlet采用Thread-Per-Request的方式處理請求,即每一次Http請求都由某一個線程從頭到尾負責處理。如果一個請求需要進行IO操作,比如訪問數據庫、調用第三方服務接口等,那么其所對應的線程將同步地等待**IO操作完成, 而IO操作是非常慢的,所以此時的線程並不能及時地釋放回線程池以供后續使用,在並發量越來越大的情況下,這將帶來嚴重的性能問題。其請求流程大致為:

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

而在Servlet3.0發布后,提供了一個新特性:異步處理請求。可以先釋放容器分配給請求的線程與相關資源,減輕系統負擔,釋放了容器所分配線程的請求,其響應將被延后,可以在耗時處理完成(例如長時間的運算)時再對客戶端進行響應。其請求流程為:

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

隨着Spring5發布,提供了一個響應式Web框架:Spring WebFlux。之后可能就不需要Servlet容器的支持了。以下是其先后對比圖:

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

原生異步請求,Servlet方式實現異步請求

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

注意:異步請求時,可以利用ThreadPoolExecutor自定義個線程池。

Spring方式實現異步請求

在Spring中,有多種方式實現異步請求,比如callable、DeferredResult或者WebAsyncTask。每個的用法略有不同,可根據不同的業務場景選擇不同的方式。以下主要介紹一些常用的用法

Callable

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

控制台輸出:

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

超時、自定義線程設置

從控制台可以看見,異步響應的線程使用的是名為:MvcAsync1的線程。第一次再訪問時,就是MvcAsync2了。若采用默認設置,會無限的創建新線程去處理異步請求,所以正常都需要配置一個線程池及超時時間。

編寫一個配置類:CustomAsyncPool.java

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

自定義一個超時異常處理類:CustomAsyncRequestTimeoutException.java

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

同時,在統一異常處理加入對CustomAsyncRequestTimeoutException類的處理即可,這樣就有個統一的配置了。

之后,再運行就可以看見使用了自定義的線程池了,超時的可以自行模擬下:

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

DeferredResult

相比於callable,DeferredResult可以處理一些相對復雜一些的業務邏輯,最主要還是可以在另一個線程里面進行業務處理及返回,即可在兩個完全不相干的線程間的通信。

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

控制台輸出:

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

注意:返回結果時記得調用下setResult方法。

題外話:利用DeferredResult可實現一些長連接的功能,比如當某個操作是異步時,我們可以保存這個DeferredResult對象,當異步通知回來時,我們在找回這個DeferredResult對象,之后在setResult會結果即可。提高性能。

WebAsyncTask

使用方法都類似,只是WebAsyncTask是直接返回了。覺得就是寫法不同而已

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

控制台輸出:

SpringBoot異步開發之異步請求,在高並發的情況下,提高性能

 

總結

主要是講解了異步請求的使用及相關配置,如超時,異常等處理。設置異步請求時,記得不要忘記設置超時時間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM