gpt4 book ai didi

java - 如何在 spring 中创建一个非阻塞的@RestController webservice?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:05:48 25 4
gpt4 key购买 nike

我有一个 @RestController web 服务方法,它可能会阻塞响应线程与长时间运行的服务调用。如下:

@RestController
public class MyRestController {
//could be another webservice api call, a long running database query, whatever
@Autowired
private SomeSlowService service;

@GetMapping()
public Response get() {
return service.slow();
}

@PostMapping()
public Response get() {
return service.slow();
}
}

问题:如果 X 用户在这里调用我的服务怎么办?执行线程将全部阻塞,直到返回响应。从而吃掉“最大连接”、最大线程等。

我记得前一段时间读过一篇关于如何解决这个问题的文章,通过某种方式停放线程直到收到缓慢的服务响应。这样那些线程就不会阻塞,例如 tomcat 最大连接/池。

但是我找不到了。也许有人知道如何解决这个问题?

最佳答案

有一些解决方案,例如使用 asynchronous requests .在这些情况下,线程将在 CompletableFutureDeferredResultCallable 返回后立即再次空闲(不一定完成)。


例如,假设我们这样配置 Tomcat:

server.tomcat.max-threads=5 # Default = 200

我们有以下 Controller :

@GetMapping("/bar")
public CompletableFuture<String> getSlowBar() {
return CompletableFuture.supplyAsync(() -> {
silentSleep(10000L);
return "Bar";
});
}

@GetMapping("/baz")
public String getSlowBaz() {
logger.info("Baz");
silentSleep(10000L);
return "Baz";
}

如果我们一次触发 100 个请求,您必须等待至少 200 秒才能处理所有 getSlowBar() 调用,因为在给定时间只能处理 5 个。另一方面,对于异步请求,您将不得不等待至少 10 秒,因为所有请求都可能会立即处理,然后该线程可供其他人使用。

CompletableFutureCallableDeferredResult 之间有区别吗?在结果方面没有任何区别,它们的行为都相似。

不过处理线程的方式有点不同:

  • 使用 Callable,您依赖 Spring 使用 TaskExecutor
  • 执行 Callable
  • 对于 DeferredResult,您必须自己进行线程处理。例如,通过执行 ForkJoinPool.commonPool() 中的逻辑。
  • 使用 CompletableFuture,您可以依赖默认线程池 (ForkJoinPool.commonPool()),也可以指定您自己的线程池。

除此之外,CompletableFutureCallable 是 Java 规范的一部分,而 DeferredResult 是 Spring 框架的一部分。


请注意,即使线程被释放,连接仍然对客户端保持打开状态。这意味着使用这两种方法,一次可以处理的最大请求数限制为 10000,并且可以配置为:

server.tomcat.max-connections=100 # Default = 10000

关于java - 如何在 spring 中创建一个非阻塞的@RestController webservice?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56055148/

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