javascript
SpringBoot异步调用方法
SpringBoot異步調用方法
?
一、spring boot--使用異步請求,提高系統的吞吐量
https://blog.csdn.net/liuchuanhong1/article/details/78744138
1.使用Callable來實現
2. 通過WebAsyncTask,也能實現異步調用
這種方式和上面的callable方式最大的區別就是,WebAsyncTask支持超時,并且還提供了兩個回調函數,分別是onCompletion和onTimeout,顧名思義,這兩個回調函數分別在執行完成和超時的時候回調。
3、Deferred方式實現異步調用
在我們是生產中,往往會遇到這樣的情景,controller中調用的方法很多都是和第三方有關的,例如JMS,定時任務,隊列等,拿JMS來說,比如controller里面的服務需要從JMS中拿到返回值,才能給客戶端返回,而從JMS拿值這個過程也是異步的,這個時候,我們就可以通過Deferred來實現整個的異步調用
-- 異步調用可以使用AsyncHandlerInterceptor進行攔截
?
二、Spring Boot異步調用(@Async)
https://blog.csdn.net/wayne_ren/article/details/84859507
異步處理
[list]
[*]Java的異步處理Thread/Runnable、Callable/Future
[*]Servlet 2.5的異步處理 Tomcat的CometProcessor、Jetty的Continuations
[*]Servlet 3.0的異步處理 asyncSupported、AsyncContext
[*]Spring MVC的異步處理 @Async、AsyncTaskExecutor
[*]Spring MVC的SSE ResponseBodyEmitter、SseEmitter、StreamingResponseBody
[/list]
Spring Boot本身對異步調用沒有多大的變動,基本還是Spring MVC的@Async。
[b](1)開啟Spring的異步支持[/b]
[color=red]開啟@EnableWebMvc的時候也自動開啟了異步處理,但在Spring Boot項目中是不能使用@EnableWebMvc的。它會使Spring Boot的AutoConfigure一部分功能失效。[/color]
官方文檔里有說明:
[url=http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration]http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration[/url]
?
三、理解Callable 和 Spring DeferredResult(翻譯)
https://www.cnblogs.com/aheizi/p/5659030.html
1-介紹
Servlet 3中的異步支持為在另一個線程中處理HTTP請求提供了可能性。當有一個長時間運行的任務時,這是特別有趣的,因為當另一個線程處理這個請求時,容器線程被釋放,并且可以繼續為其他請求服務。
這個主題已經解釋了很多次,Spring框架提供的關于這個功能的類似乎有一點混亂——在一個Controller中返回Callable 和 DeferredResult。
在這篇文章中,我將實施這兩個例子,以顯示其差異。
這里所顯示的所有示例都包括執行一個控制器,該控制器將執行一個長期運行的任務,然后將結果返回給客戶機。長時間運行的任務由taskservice處理:
這個web應用是用Spring Boot創建的,我們將執行下面的類來運行我們的例子:
@SpringBootApplication public class MainApp {public static void main(String[] args) {SpringApplication.run(MainApp.class, args);} }2-阻塞的Controller
在這個例子中,一個請求到達控制器。servlet線程不會被釋放,直到長時間運行的方法被執行,我們退出@requestmapping注釋的方法。
@RestController public class BlockingController {private final Logger logger = LoggerFactory.getLogger(this.getClass());private final TaskService taskService;@Autowiredpublic BlockingController(TaskService taskService) {this.taskService = taskService;}@RequestMapping(value = "/block", method = RequestMethod.GET, produces = "text/html")public String executeSlowTask() {logger.info("Request received");String result = taskService.execute();logger.info("Servlet thread released");return result;} }如果我們運行這個例子http://localhost:8080/block,在日志里我們會發現servlet request不會被釋放,直到長時間的任務執行完(5秒后)。
2015-07-12 12:41:11.849 [nio-8080-exec-6] x.s.web.controller.BlockingController : Request received 2015-07-12 12:41:16.851 [nio-8080-exec-6] x.spring.web.service.TaskServiceImpl : Slow task executed 2015-07-12 12:41:16.851 [nio-8080-exec-6] x.s.web.controller.BlockingController : Servlet thread released3-返回Callable
在這個例子中,不是直接返回的結果,我們將返回一個Callable:
@RestController public class AsyncCallableController {private final Logger logger = LoggerFactory.getLogger(this.getClass());private final TaskService taskService;@Autowiredpublic AsyncCallableController(TaskService taskService) {this.taskService = taskService;}@RequestMapping(value = "/callable", method = RequestMethod.GET, produces = "text/html")public Callable<String> executeSlowTask() {logger.info("Request received");Callable<String> callable = taskService::execute;logger.info("Servlet thread released");return callable;} }返回Callable意味著Spring MVC將調用在不同的線程中執行定義的任務。Spring將使用TaskExecutor來管理線程。在等待完成的長期任務之前,servlet線程將被釋放。
2015-07-12 13:07:07.012 [nio-8080-exec-5] x.s.w.c.AsyncCallableController : Request received 2015-07-12 13:07:07.013 [nio-8080-exec-5] x.s.w.c.AsyncCallableController : Servlet thread released 2015-07-12 13:07:12.014 [ MvcAsync2] x.spring.web.service.TaskServiceImpl : Slow task executed你可以看到我們在長時間運行的任務執行完畢之前就已經從servlet返回了。這并不意味著客戶端收到了一個響應。與客戶端的通信仍然是開放的等待結果,但接收到的請求的線程已被釋放,并可以服務于另一個客戶的請求。
4-返回DeferredResult
首先,我們需要創建一個deferredresult對象。此對象將由控制器返回。我們將完成和Callable相同的事,當我們在另一個線程處理長時間運行的任務的時候釋放servlet線程。
@RestController public class AsyncDeferredController {private final Logger logger = LoggerFactory.getLogger(this.getClass());private final TaskService taskService;@Autowiredpublic AsyncDeferredController(TaskService taskService) {this.taskService = taskService;}@RequestMapping(value = "/deferred", method = RequestMethod.GET, produces = "text/html")public DeferredResult<String> executeSlowTask() {logger.info("Request received");DeferredResult<String> deferredResult = new DeferredResult<>();CompletableFuture.supplyAsync(taskService::execute).whenCompleteAsync((result, throwable) -> deferredResult.setResult(result));logger.info("Servlet thread released");return deferredResult;} }所以,返回DeferredResult和返回Callable有什么區別?不同的是這一次線程是由我們管理。創建一個線程并將結果set到DeferredResult是由我們自己來做的。
用completablefuture創建一個異步任務。這將創建一個新的線程,在那里我們的長時間運行的任務將被執行。也就是在這個線程中,我們將set結果到DeferredResult并返回。
是在哪個線程池中我們取回這個新的線程?默認情況下,在completablefuture的supplyasync方法將在forkjoin池運行任務。如果你想使用一個不同的線程池,你可以通過傳一個executor到supplyasync方法:
如果我們運行這個例子,我們將得到如下結果:
2015-07-12 13:28:08.433 [io-8080-exec-10] x.s.w.c.AsyncDeferredController : Request received 2015-07-12 13:28:08.475 [io-8080-exec-10] x.s.w.c.AsyncDeferredController : Servlet thread released 2015-07-12 13:28:13.469 [onPool-worker-1] x.spring.web.service.TaskServiceImpl : Slow task executed5-結論
站在一定高度來看這問題,Callable和Deferredresult做的是同樣的事情——釋放容器線程,在另一個線程上異步運行長時間的任務。不同的是誰管理執行任務的線程。
文中涉及的代碼spring-rest
翻譯自Xavier Padró's Blog
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的SpringBoot异步调用方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android培训之android下大文
- 下一篇: 树莓派+温度模块