Java - 长轮询(long polling)实现

  • 前言
  • 阻塞long polling
  • 非阻塞long polling
    • Servlet
    • Spring
  • 参考

前言

本文假设读者对于长轮询有一定的了解。
如不了解,可参考如下一些文章:

  • Web通信之长连接、长轮询(long polling)
  • Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

阻塞long polling

基于Servlet实现的阻塞long polling的例子可参考:
Long Polling长轮询详解

阻塞long polling的问题在于,每个请求会阻塞一个tomcat/jetty线程,并发性非常差。这时候就需要使用非阻塞的接口。

非阻塞long polling

Servlet

从Servlet 3.0开始,支持异步处理请求。使用异步处理doGet方法执行完成后,结果也不会返回到客户端,会等到请求的context被complete才会写回客户端。使用这种方法,可极大提升long polling的并发处理能力。

代码示例可参考:Long Polling长轮询实现进阶

Spring

当前,大多数公司都是使用spring来开发的。spring也支持了异步处理。实现类是DeferredResult

下面是使用spring进行异步处理的代码示例:

@GetMapping("/async-deferredresult")
public DeferredResult> handleReqDefResult(Model model) {
    LOG.info("Received async-deferredresult request");
    DeferredResult> output = new DeferredResult<>();
     
    ForkJoinPool.commonPool().submit(() -> {
        LOG.info("Processing in separate thread");
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
        }
        output.setResult(ResponseEntity.ok("ok"));
    });
     
    LOG.info("servlet thread freed");
    return output;
}

DeferredResult支持设置超时,即在后端一致没有数据的情况下,多长时间断开连接。使用的是onTimeout()方法。
以下是代码示例:

DeferredResult> deferredResult = new DeferredResult<>(500l);
 
deferredResult.onTimeout(() -> 
  deferredResult.setErrorResult(
    ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT)
      .body("Request timeout occurred.")));

我们模拟6s后才有数据返回,如下:

ForkJoinPool.commonPool().submit(() -> {
    LOG.info("Processing in separate thread");
    try {
        Thread.sleep(6000);
    } catch (InterruptedException e) {
        ...
    }
    deferredResult.setResult(ResponseEntity.ok("OK")));
});

但是由于设置了onTimeout(),500ms时,连接也会断开。

如果后端出现了错误,可以设置onError()方法修改返回状态码:

deferredResult.onError((Throwable t) -> {
    deferredResult.setErrorResult(
      ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
        .body("An error occurred."));
});

参考

  • Guide to DeferredResult in Spring [荐]
  • springMvc DeferredResult的long polling应用
  • Long Polling长轮询详解
  • Long Polling长轮询实现进阶

你可能感兴趣的:(Java - 长轮询(long polling)实现)