如何解决Spring Boot REST - 将 ThreadPoolTaskExecutor 用于单个作业
我加入了公司的一个新团队,我看到他们广泛使用“ThreadPoolTaskExecutor”。它基本上是前端的后端 REST 应用程序,它调用其他 SOAP API 并将结果返回给客户端 - 只是一个传递。 99% 的情况下,每个 REST 端点仅调用单个 SOAP API 并将响应以 json 格式返回给客户端。然而,虽然它只是一个单一的 SOAP 调用,但它们使用了“ThreadPoolTaskExecutor”并调用了 .get() 阻塞方法。
ThreadPoolTaskExecutor @Bean 在 @Configuration 类上:
@Bean(name=“soapAsyncExecutor")
@Qualifier("soapAsyncExecutor")
public ThreadPoolTaskExecutor getSoapAsyncExecutor() {
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
final ThreadFactory customThreadfactory = new ThreadFactoryBuilder()
.setNameFormat(“SoapExecutor-%d")
.setUncaughtExceptionHandler(uncaughtExceptionHandler())
.setDaemon(true)
.build();
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setCorePoolSize(80);
executor.setMaxPoolSize(200);
executor.setQueueCapacity(80);
executor.setKeepAliveSeconds(60);
executor.setAllowCoreThreadTimeOut(true);
executor.setThreadFactory(customThreadfactory);
executor.afterPropertiesSet();
return executor;
}
@Service 上的代码:
@Async("soapAsyncExecutor")
@Override
public Future<OrderInfo> getorderInfoAsync(final String orderId) {
return new AsyncResult<OrderInfo>(this.getorderInfo(orderId);
}
private OrderInfo getorderInfo(final String orderId) {
// return result from SOAP call which typically take 1 second
}
然后从 @RestController 上面这样调用异步方法:
@GetMapping(value = "/order/{orderId}")
public OrderInfo getorderInfo(@PathVariable("orderId") final String orderId) {
OrderInfo orderInfo = orderService.getorderInfoAsync(orderId).get();
return orderInfo;
}
据我所知,Spring 中对 REST 端点的每个请求,无论如何都会启动一个新线程(由于我没有更好的词,我们将其称为主线程)。并在那里调用“.get()”方法会阻塞主线程。我的问题是,在这个封锁期间,
- 主线程的官方状态是什么——“阻塞”还是“等待”?如果被阻塞,对单个作业使用这样的“ThreadPoolTaskExecutor”是否有丝毫好处,因为它无论如何都会阻塞主线程?
- 是否可以通过任何方式调整此代码以带来好处,还是在 RestController 端点内为这样的单个作业使用异步编程毫无意义?
解决方法
主线程的官方状态是什么——“阻塞”或“等待”?
已阻止。
如果被阻塞,对于单个作业使用这样的“ThreadPoolTaskExecutor”是否有丝毫好处,因为它无论如何都会阻塞主线程?
没有。空无一人。事实上,我敢打赌将任务分派到线程池会带来额外的开销。不过,如果端点要等待多个任务完成,这是有道理的。
可以以任何方式调整此代码以带来好处,还是在 RestController 端点内为单个作业使用异步编程毫无意义?
当然。这是an example。这是another one。本质上,在您的场景中,只需返回 CompletableFuture
而不是调用 .get()
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。