# http-long-polling **Repository Path**: ssp198/http-long-polling ## Basic Information - **Project Name**: http-long-polling - **Description**: 基于HTTP的长轮询实现 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2022-08-09 - **Last Updated**: 2024-02-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: SpringBoot, Java, Http, long-polling ## README ### A demo of http-long-polling ——基于HTTP的长轮询 #### 长轮询简介 * *HTTP的通信基本特点:半双工通信、“一请求一响应”。* * *简单轮询:简单轮询方式是由客户端控制轮询调用间隔。在使用HTTP协议且有一定的实时性要求的业务场景下,一般会通过减小资源调用方对接口的轮询时间间隔来确保“一定的”实时性,但过小的轮询间隔会增大客户端服务端双方CPU和网络等宽等资源消耗,为了权衡资源消耗和实时性,轮询间隔一般不会太短,大多是秒级,从而避免不了有恒定的延时。* * *长轮询:长轮询机制可缓解简单轮询带有的资源浪费问题,又可以保证更高的实时性。实现思路就是交由服务端控制http-rpc轮询周期来保证实时性,客户端调大``socket-timeout``读超时时长,服务端在超时前返回响应,这个超时时长可以设置的长一点,如30秒。* #### 长轮询特点 ~~~ 基于HTTP协议的长轮询在实时性上比上websocket稍有不足,比下HTTP简单轮询有余。 ~~~ #### 实现:基于AsyncContext——servlet异步请求 * servlet对异步请求做出了规范 ```java package javax.servlet; public interface ServletRequest { public AsyncContext startAsync(); public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse); } ``` * 直接在SpringMVC中使用 ```java HttpServletRequest request; HttpServletResponse response; AsyncContext asyncContext = request.startAsync((request, response); //开启异步请求上下文 ``` #### 快速使用 *详见`io.longpolling.test.controller.ResourceController`用例* * 对客户端请求开启异步任务. ```java public class ResourceController { private static final String RESOURCE_SAY_HELLO = "SayHello"; @GetMapping("/waitSayHello") public void waitSayHello(HttpServletRequest request, HttpServletResponse response, String who, Integer timeout) { //请求基础信息 RequestParam curRequestParam = RequestParam.newInstance(RESOURCE_SAY_HELLO, who); //响应超时设置及返回结果 TimeoutResult timeoutResult = TimeoutResult.newInstance(timeout, "Resp Timeout, but hello world for you!", HttpStatus.REQUEST_TIMEOUT); //开启异步响应 AsyncResponseTask.buildAndStart(request, response, curRequestParam, timeoutResult); } } ``` * 处理异步请求-响应任务 ```java public class ResourceController { private static final String RESOURCE_SAY_HELLO = "SayHello"; @PutMapping("/sayHello") public String sayHelloForWe() { final Collection sayHelloRespTaskWaitList = AsyncResponseTask.getAsyncTask(RESOURCE_SAY_HELLO); final int total = sayHelloRespTaskWaitList.size(); sayHelloRespTaskWaitList.forEach(asyncResp -> { RequestParam requestParam = asyncResp.getRequestParam(); String who = (String) requestParam.getParam(); String result = String.format("Hello %s!", who); asyncResp.returnJsonResult(result, HttpStatus.OK); //完成异步响应 log.debug("--->say hello for {} success!", who); }); return String.format("say hello for %s people!", total); } } ```