如何在 Spring Boot 应用程序中实现长轮询 REST 端点?

问题描述 投票:0回答:2

您能否分享任何最新的手册或在这里解释如何使用最新的 Spring (Spring Boot) 实现 REST 长轮询端点?

我此时发现的所有内容都已经过时,并且是几年前发布的。

所以,我提出了一个问题,长轮询仍然是一个好方法吗?我知道 chess.com 中使用了它

java rest spring-mvc spring-boot long-polling
2个回答
26
投票

对于长轮询请求,您可以使用

DeferredResult
。当您返回
DeferredResult
响应时,请求线程将空闲,并且该请求将由工作线程处理。这是一个例子:

@GetMapping("/test")
DeferredResult<String> test(){
    long timeOutInMilliSec = 100000L;
    String timeOutResp = "Time Out.";
    DeferredResult<String> deferredResult = new DeferredResult<>(timeOutInMilliSec, timeOutResp);
    CompletableFuture.runAsync(()->{
        try {
            //Long polling task; if task is not completed within 100s, timeout response returned for this request
            TimeUnit.SECONDS.sleep(10);
            //set result after completing task to return response to client
            deferredResult.setResult("Task Finished");
        }catch (Exception ex){
        }
    });
    return deferredResult;
}

此请求演示等待 10 秒后提供响应。如果您设置

sleep(100)
或更长时间,您将收到超时响应。

查看this以获取更多选项。


0
投票

请注意,使用 Spring MVC 堆栈时,如果不利用 NIO 组件(例如 Reactive Stack 中的组件),就不可能创建有效的长轮询实现。

阻塞实现效率如此低下的原因是,即使您生成了一个新线程,它们也会阻塞正在运行的线程。当您像 @GolamMazid Sajib 的答案一样生成一个新线程时,您只需更改被阻止的线程即可。虽然现在工作线程是空闲的,但是后台线程正在被阻塞。

假设您已经创建了 @GolamMazid Sajib 提供的长轮询解决方案:

@GetMapping("/test")
DeferredResult<String> test(){
    long timeOutInMilliSec = 100000L;
    String timeOutResp = "Time Out.";
    DeferredResult<String> deferredResult = new DeferredResult<>(timeOutInMilliSec, timeOutResp);
    CompletableFuture.runAsync(()->{
        try {
            //Long polling task; if task is not completed within 100s, timeout response returned for this request
            TimeUnit.SECONDS.sleep(10);
            //set result after completing task to return response to client
            deferredResult.setResult("Task Finished");
        }catch (Exception ex){
        }
    });
    return deferredResult;
}

CompletableFuture.runAsync
方法将执行上下文更改为线程池。

现在,假设您同时收到 1000 个请求。现在,每个工作线程立即处理 1000 个请求。然而,后台线程池现在成为瓶颈。假设池中有 50 个线程。您的吞吐量变为每秒 5 个请求。此外,请求花费的时间远远超过 10 秒,因为它们必须等待后台线程完成。大多数请求都会因为100秒超时而超时。

如果你想实现长轮询,你应该考虑实现 NIO 解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.