Java - 长轮询(long polling)实现

前言

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

阻塞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<ResponseEntity<?>> handleReqDefResult(Model model) {
    LOG.info("Received async-deferredresult request");
    DeferredResult<ResponseEntity<?>> 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<ResponseEntity<?>> 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."));
});

参考

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 最近前任三大火,哭的哭,乐的乐,感慨的感慨,概括的概括,空间动态,微信朋友圈,一个接着一个,感觉走到哪说的...
    逍遥逸阅读 327评论 0 0
  • 当一个久违的电话,突然打来。没有喜悦,没有忧伤,一切似乎都是那么的理所当然,那么自然。但又似乎有着某种无法言说的...
    墨墨黒阅读 250评论 0 0
  • 双鱼座的她,从来没有想到自己有一天会和“相夫教子”这四个字联系在一起,就算作为女人不得不和这几个字链接,自己应该也...
    自己在这里阅读 454评论 0 0