福建省网站备案,wordpress 开启xmlrpc,校园交友的网站建设,网易企业邮箱登录v最近遇到了一个问题#xff0c;我们的一个接口需要去轮询另一个第三方接口#xff0c;导致这个接口占用了太多工作线程#xff0c;这些工作线程长时间 running#xff0c;我们需要解决这个问题。 于是#xff0c;我们的方案是#xff1a;用 DeferredResult 实现接口异步。… 最近遇到了一个问题我们的一个接口需要去轮询另一个第三方接口导致这个接口占用了太多工作线程这些工作线程长时间 running我们需要解决这个问题。 于是我们的方案是用 DeferredResult 实现接口异步。 我们下面讲讲原理 … DeferredResult 所属包package org.springframework.web.context.request.async; 我们先实测一波 PostMapping(/pay3)public DeferredResultInteger pay3() {log.info(开始支付3...);DeferredResultInteger result new DeferredResult(60000L);new Thread(() - {try {result.setResult(checkPayStatus());} catch (Throwable cause) {result.setErrorResult(cause.getMessage());}}).start();return result;}private Integer checkPayStatus() {for (int i 0; i 5; i) {try {log.info(查询支付状态第 {} 次查询, i);Thread.sleep(10000L);} catch (InterruptedException e) {throw new RuntimeException(e);}}log.info(查询支付状态返回成功);return 1;}工作线程 XNIO-1 task-2 创建线程后就跑到了最后的返回。 按以前都是直接返回结果了但是由于我们是声明了 DeferredResult 作为 SpringMVC 的返回参数则此时返回结果并没有真的返回接口没有返回但工作线程也没有被阻塞住工作线程为 WAIT 状态TIMED_WAITING。 工作线程是什么时候挂起的呢 探究如下 PostMapping(/pay3)public DeferredResultInteger pay3() {log.info(开始支付3...);DeferredResultInteger result new DeferredResult(60000L);new Thread(() - {try {result.setResult(checkPayStatus());} catch (Throwable cause) {result.setErrorResult(cause.getMessage());}}).start();try {log.info(返回前的主线程等待 开始..);Thread.sleep(100000L);log.info(返回前的主线程等待 结束..);} catch (InterruptedException e) {throw new RuntimeException(e);}log.info(返回结果);return result;}从执行结果可以看出如果没有走到 return 结果那么 SpringMVC 是不会将工作线程挂起的这也很好理解。 连接是被hold住的响应是最后才返回给客户端我们的代码就在这中间前提是我们开启了新线程 而且 有别于 Callable 是 hold 住异步代码Deferred 是 hold 住返回值。
https://stackoverflow.com/questions/17855852/difference-between-spring-mvcs-async-deferredresult-and-callable 这里用的是 ForkJoinPool.commonPool() 公共线程池去创建子工作的例子。 创建了新的线程意味着更多的计算资源但是工作线程不会被阻塞因此可以处理更多的请求。 这也在我们测试中被验证如果不用此方法我们的 undertow 容器默认的 16 工作线程根本不够用会导致 k8s 重启 容器。
https://www.baeldung.com/spring-deferred-result 这里用的是 CompletableFuture 异步处理去创建的跟上面是一个道理。 https://www.javacodegeeks.com/2015/07/understanding-callable-and-spring-deferredresult.html
官方文献 前半段比较有含金量就是说 DeferredResult 是 Callable 的替代两者都可以实现接口的异步但是DeferredResult 是可以让子线程去协助返回的也就是说我们有更多的操作空间。后半段就是说可以通过继承或者其他操作来完成更多的骚操作。
综上我们可以发现几个关键词
异步工作 asynchronous task和 Callable 的相似性是springmvc的东西不能脱离spring进行。我们知道 Callable 是 java.util.concurrent 的东西一般是用来处理长等待的请求。服务器释放
DeferredResult 是不能不创建子线程实现异步的。 测试如下 PostMapping(/pay4)public DeferredResultInteger pay4() {log.info(开始支付4...);DeferredResultInteger result new DeferredResult(60000L);result.setResult(checkPayStatus());return result;}我们稍微思考下就可以得知我们的长逻辑直接在工作线程中跑了自然是阻塞了。 ~~
不过需要注意的是对于前端或者这个接口的调用方来说接口依然是同步的。 我们的接口相当于一个黑盒我们内部进行的异步让我们可以用其他线程帮助处理业务逻辑工作线程可以去协调这些工作逻辑从而实现同时处理更多请求。
创作不易希望大佬们点赞、收藏、关注~