如何在春季创建一个非阻塞的@RestController Web服务? [英] How to create a non-blocking @RestController webservice in spring?

查看:150
本文介绍了如何在春季创建一个非阻塞的@RestController Web服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个@RestController webservice方法,该方法可能会通过长时间运行的服务调用来阻塞响应线程.如下:

I'm having a @RestController webservice method that might block the response thread with a long running service call. As follows:

@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个用户在这里呼叫我的服务怎么办?执行线程将全部阻塞,直到返回响应.这样就吃掉了最大连接数",最大线程数.

Problem: what if X users are calling my service here? The executing threads will all block until the response is returned. Thus eating up "max-connections", max threads etc.

我记得前段时间读过一篇有关如何解决此问题的文章,该文章以某种方式驻留线程,直到收到缓慢的服务响应为止.这样这些线程就不会阻塞例如tomcat最大连接/池.

I remember some time ago a read an article on how to solve this issue, by parking threads somehow until the slow service response is received. So that those threads won't block eg the tomcat max connection/pool.

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

But I cannot find it anymore. Maybe somebody knows how to solve this?

推荐答案

有一些解决方案,例如使用

there are a few solutions, such as working with asynchronous requests. In those cases, a thread will become free again as soon as the CompletableFuture, DeferredResult, Callable, ... is returned (and not necessarily completed).

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

For example, let's say we configure Tomcat like this:

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

我们有以下控制器:

@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秒钟,因为所有请求很可能会立即处理,然后其他人可以使用该线程.

If we would fire 100 requests at once, you would have to wait at least 200 seconds before all the getSlowBar() calls are handled, since only 5 can be handled at a given time. With the asynchronous request on the other hand, you would have to wait at least 10 seconds, because all requests will likely be handled at once, and then the thread is available for others to use.

CompletableFutureCallableDeferredResult之间是否有区别?结果方面没有任何区别,它们的行为都相似.

Is there a difference between CompletableFuture, Callable and DeferredResult? There isn't any difference result-wise, they all behave the similarly.

您处理线程的方式有所不同:

The way you have to handle threading is a bit different though:

  • 对于Callable,您依靠Spring使用TaskExecutor
  • 执行Callable
  • 使用DeferredResult,您必须自己处理线程.例如,通过执行ForkJoinPool.commonPool()中的逻辑.
  • 使用CompletableFuture,您可以依赖默认线程池(ForkJoinPool.commonPool()),也可以指定自己的线程池.
  • With Callable, you rely on Spring executing the Callable using a TaskExecutor
  • With DeferredResult you have to to he thread-handling by yourself. For example by executing the logic within the ForkJoinPool.commonPool().
  • With CompletableFuture, you can either rely on the default thread pool (ForkJoinPool.commonPool()) or you can specify your own thread pool.

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

Other than that, CompletableFuture and Callable are part of the Java specification, while DeferredResult is a part of the Spring framework.

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

Be aware though, even though threads are released, connections are still kept open to the client. This means that with both approaches, the maximum amount of requests that can be handled at once is limited by 10000, and can be configured with:

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

这篇关于如何在春季创建一个非阻塞的@RestController Web服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆