gpt4 book ai didi

multithreading - 使用 Spring boot 和 CompletableFuture 及其线程管理编写异步 Rest API

转载 作者:行者123 更新时间:2023-12-05 04:49:09 28 4
gpt4 key购买 nike

我对 tomcat 服务器和应用程序的线程管理有疑问。这是一个示例代码:

@RequestMapping(path = "/asyncCompletable", method = RequestMethod.GET)
public CompletableFuture<String> getValueAsyncUsingCompletableFuture() {

logger.info("Request received");
CompletableFuture<String> completableFuture
= CompletableFuture.supplyAsync(this::processRequest);
logger.info("Servlet thread released");
return completableFuture;

}

private String processRequest() {
Long delayTime = 10000L;
logger.info("Start processing request");
try {
Thread.sleep(delayTime);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
logger.info("Completed processing request");
return "Processing done after " + delayTime;
}

在这里,这是一个使用 spring boot 的简单 API。我在这里做了什么?

  • 这是一个简单的端点,它是一个简单的 GET 方法并返回一个字符串作为响应。
  • 在方法 getValueAsyncUsingCompletableFuture 中,我在 CompletableFuture.supplyAsync(this::processRequest) 上调用 processRequest。所以很明显它将在单独的线程下运行。
  • 在方法 processRequest 中只有一个 Thread.sleep 10s。
  • 这两种方法都有进入和退出日志。
  • 此外,API getValueAsyncUsingCompletableFuture 正在返回一个 completableFuture

现在,从浏览器调用端点后,其输出符合预期。它等待 10 秒并提供响应。输出日志如下。 enter image description here

这里,

  • 日志的第一行和第二行显示在nio-8080-exec-8线程下。它还显示收到请求和释放的 servlet 线程。
  • 在方法 processRequest 的最后 2 行日志中。这里显示的是 CompletableFuture 执行部分。它在 onPool-worker-2 线程下处理。

现在,这是我的问题:

  1. processRequest方法执行过程中,是否释放了tomcat分配的线程nio-8080-exec-8?我是根据日志说的。是否释放该线程并返回tomcat连接池?
  2. 如果 tomcat 线程已释放,那么客户端如何在 completableFuture 执行完成后获得响应?
  3. 能否请您描述一下当请求到达 tomcat 服务器和 spring 应用程序时线程分配是如何发生的。

提前致谢

最佳答案

Spring 使用 ServletRequest#startAsync() Servlet 3.0 中引入的方法(参见 Oracle's tutorial )。这意味着:

  1. 调用 getValueAsyncUsingCompletableFuture 后不久,Tomcat 线程 http-nio-8080-exec-8 返回到其执行程序,但响应尚未提交给客户端与同步情况一样。每当您的处理程序返回 CompletionStage 时,Spring 都会将 ServletRequest 切换到异步模式.
  2. 在您的方法 getValueAsyncUsingCompletableFuture 退出后,ServletRequestServletResponse 仍可用于向客户端发送数据。 Spring 向您的 CompletableFuture 附加一个阶段,它将结果写入 ServletResponse 并使用 AsyncContext#complete() 结束请求。这个阶段可以在任何线程上执行。在您的情况下,它在 ForkJoinPool 上执行,因为您使用默认执行程序启动了 CompletableFuture 。但是,任何遗嘱执行人都可以。
  3. Tomcat 分配一个线程来执行 getValueAsyncUsingCompletableFuture(或者更准确地说是 DispatcherServlet#service)。其余的分配由您决定。

关于multithreading - 使用 Spring boot 和 CompletableFuture 及其线程管理编写异步 Rest API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67708402/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com