博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringMVC DeferedResult和servlet3.1 AsyncContext异步请求
阅读量:4946 次
发布时间:2019-06-11

本文共 2915 字,大约阅读时间需要 9 分钟。

 

先看一个简单的示例:

1 @RequestMapping("/getFuture") 2 public Future
getFuture() { 3 System.out.println(1); 4 // 必须是ListenableFuture的子类,或者CompletionStage子类,或者是DeferredResult 不能是FutureTask 5 // 如何返回CompletableFuture 6 CompletableFuture
ftu2 = CompletableFuture.supplyAsync(() -> { 7 try { 8 // RequestContextHolder.setRequestAttributes(attributes); 9 // 使用ThreadLocal相关特性时,需要在外面先get10 Thread.sleep(3000L);11 } catch (InterruptedException e) {12 } finally {13 // RequestContextHolder.resetRequestAttributes();14 }15 return "THIS string";16 }, es);17 18 //Future
future = executorService.submit(() -> { }); //返回值是FutureTask19 20 return ftu2;21 }

 

 

客户端发起请求 ===> DispatcherServlet根据返回值类型查找对应的handlar AsyncHandlerMethodReturnValueHandler             【Callable --> CallableMethodReturnValueHandler;  DeferredResult,CallableFuture,ListenableFuture --> DeferredResultMethodReturnValueHandler】
===> Controller中返回Future对象给容器, org.springframework.web.context.request.async.WebAsyncManager#startDeferredResultProcessing处理Future结果的监听 ===> sleep3秒之后,Future完成后调用asyncWebRequest.dispatch() 重新发给Container,DispatcherServlet找到Message的序列化器将结果输出。DispatcherServlet.doService会进入两次!!!
异步线程的主要功能是: 业务处理耗较长(上面的sleep3)时,可以先返回Future对象释放Container的work线程, work线程可以接收更多的请求。等Future完成之后重新调用Container的另一个work线程,输出response. 这里work线程可以是BIO中work线程, 也可以是NIO中work线程 不是所有的Future都能在异步线程中处理 https://www.cnblogs.com/dennyzhangdd/p/7010972.html spring boot中配置container的work线程数量 server.tomcat.max-threads=5 server.tomcat.min-spare-threads=3
  使用异步处理的优点:增加系统吞吐量,对响应速度提高不大,可能还会降低 缺点: 线程关系复杂, 异步超时、异常日志拦截需要实现具体的Adapter接口,threadLocal不好清理 参考:《亿级流量架构核心技术》       Servlet3.1 规范
    tomcat线程配置
遗留问题: Future.get是什么时候调用的? 没有直接调用get。 ListenerableFuture, CompletableFuture任务完成之后都会触发回调 work1线程:  接收到请求---> DispatcherServlet--> return future -->WebAsyncManager#startDeferredResultProcessing 自定义的任务线程: CompletableFuture.postComplete之后调用 WebAsyncManager#setConcurrentResultAndDispatch work2线程:  dipatch ---> DispatcherServlet --> response.out 关于第二个任务线程: 当返回值是Callable时,调用WebAsyncManager#startCallableProcessing, 此时任务线程使用的是AsyncTaskExecutor, 可以通过org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#configureAsyncSupport设置自定义的AsyncTaskExecutor 当返回值是DeferredResult,ListenableFuture (Spring提供),CompletableFuture(JDK自带)时,调用WebAsyncManager#startDeferredResultProcessing,此时任务线程池可以直接指定 @See CompletableFuture.supply(xxxTask, threadPool)
@RequestMapping("/callableTest")public Callable
callableTest() { Callable
hello = () -> { // 此处不能设置线程池, WebAsyncManager中会使用AsyncSupportConfigurer的线程池 System.out.println("===>" + Thread.currentThread().getName()); return "HELLO"; }; return hello;}

 

 

转载于:https://www.cnblogs.com/yszzu/p/9520590.html

你可能感兴趣的文章
高校表白APP-冲刺第四天
查看>>
outlook 设置163邮箱
查看>>
mysql优化——show processlist命令详解
查看>>
Solr服务器搭建
查看>>
画世界怎么用光影_世界绘画经典教程:水彩光影魔法教程
查看>>
win+rsync+php,跨平台的fswatch+rsync同步备份
查看>>
vue2 cdn 加载html,vue项目中使用CDN加载
查看>>
github.com访问慢解决
查看>>
转:哈夫曼树详解
查看>>
.Net Core Identity外面使用Cookie中间件
查看>>
C#中泛型之Dictionary
查看>>
Codeforces Round #376 (Div. 2)
查看>>
Codeforces 607D Power Tree 线段树 (看题解)
查看>>
写在人生的路上——2016年上半年总结
查看>>
C语言、C语言的起源以及类似C语言的编程语言的历史简直不要太漫长,我简单总结列表如下:...
查看>>
sp1.3-1.4 Neural Networks and Deep Learning
查看>>
SQL 将一个表中的所有记录插入到一个临时表中
查看>>
nmea协议
查看>>
js 中对象的特性
查看>>
hdoj3714【三分】
查看>>