Apollo(2) 长轮询

作者: Oliver_Li | 来源:发表于2022-12-08 22:11 被阅读0次
  • 在三个主要service之前先写一个Apollo关键的知识点DeferredResult,关联Apollo(3) Config Service部分
  1. 长链接、长轮询概念:https://blog.csdn.net/joeries/article/details/91389939
  • 最大区别是http长轮询不会立即返回,服务端挂起,触发某些事件才会返回。如果有兴趣还可以看看websocket实现了全双工通信也可以解决服务端推送问题
  1. DeferredResult:springMvc DeferredResult的long polling应用 | KL博客
  • spring在服务端实现长轮询请求挂起的机制,挂起后节省资源占用,setResult()后真正触发响应
  1. DeferredResult原理见博客,下面的代码根据博客代码进行改造,更贴近Apollo长轮询的服务端源码逻辑,模拟了包括Config Service接收Client请求、Config Service接收到Admin Service监听时setResult()返回消息,长轮训是Apollo最重要的逻辑之一
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.Map;

/**
 * 模拟两个Client长轮训请求:localhost:9998/async/longPolling?namespace=namespace1、localhost:9998/async/longPolling?namespace=namespace2
 * 模拟触发监听响应Client:localhost:9998/async/returnLongPollingValue?namespace=namespace1
 */
@RestController
@RequestMapping("/async")
public class DeferredResultController {
    final Map<String, DeferredResult<ResponseEntity<String>>> deferredResultMap = new ConcurrentReferenceHashMap<>(); // 存deferredResult的Map

    private static final ResponseEntity<String> STATUS_304 = new ResponseEntity<>(HttpStatus.NOT_MODIFIED); // http 304

    @GetMapping("/longPolling")
    public DeferredResult<ResponseEntity<String>> DeferredResultLongPolling(String namespace) {
        // 初始化DeferredResult,超时5s后返回304,如果被setResult()也会触发响应
        DeferredResult<ResponseEntity<String>> deferredResult = new DeferredResult<>(5000L, STATUS_304);
        // 加入到全局集合deferredResultMap,否则returnLongPollingValue接口获取不到DeferredResult对象
        deferredResultMap.put(namespace, deferredResult);
        System.out.println("deferredResult.hashCode()" + deferredResult.hashCode());
        // 超时、deferredResult.setResult()都会回调onCompletion(),代表Map里的DeferredResult使用结束后必须被清掉
        deferredResult.onCompletion(() -> {
            deferredResultMap.remove(namespace);
            System.err.println("还剩" + deferredResultMap.size() + "个deferredResult未响应");
        });
        // controller会正常执行,但response会被拦住不会返回客户端,超时或者DeferredResult被setResult()才会真正响应给客户端
        return deferredResult;
    }

    @GetMapping("/returnLongPollingValue")
    public void returnLongPollingValue(String namespace) {
        // 模拟Apollo Config Service发布触发listener回调,返回200并带上namespace最新的release message表ID,后续Client会根据ID查具体配置
        DeferredResult<ResponseEntity<String>> deferredResult = deferredResultMap.get(namespace);
        ResponseEntity<String> response = new ResponseEntity<>(namespace + " new release message ID!", HttpStatus.OK);
        deferredResult.setResult(response);
    }
}

相关文章

  • Apollo 8 — ConfigService 异步轮询接口的

    源码 Apollo 长轮询的实现,是通过客户端轮询 /notifications/v2 接口实现的。具体代码在 c...

  • Apollo 长轮询超时错误

    最近线上碰到一个线上的go程序Apollo报错,请求apollo的时候超时,记录一下错误的原因。 错误信息 Apo...

  • http长短连接和长短轮询、webSocket

    本文主要介绍长连接、短连接、长轮询、短轮询 和 webSocket。长连接、短连接、长轮询、短轮询是基于http的...

  • 长轮询&短轮询

    一、http协议 http 协议是请求/响应范式的,每一个 http 响应都是由一个对应的 http 请求产生的,...

  • 轮询与长轮询

    数据交互有两种模式:Push(推模式)、Pull(拉模式)。 1 推模式指的是客户端与服务端建立好网络长连接,服务...

  • 长轮询 短轮询

    短轮询相信大家都不难理解,比如你现在要做一个电商中商品详情的页面,这个详情界面中有一个字段是库存量(相信这个大家都...

  • 轮询、长轮询、长连接、websocket

    短轮询 基本思路:浏览器每隔一段时间向浏览器发送http请求,服务器端在收到请求后,不论是否有数据更新,都直接进行...

  • 轮询、长轮询、长连接、websocket

    今天做一个档案项目,一个内容的状态是随时发生变化的,后端和我说这里要做轮询,我一听轮询一时间没有反应过来,查阅了相...

  • 轮询、长轮询、长连接、WebSocket

    Web端即时通讯技术:即时通讯技术简单的说就是实现这样一种功能:服务器端可以即时地将数据的更新或变化反应到客户端,...

  • ES6 8.Generator

    实例:1.前端实现抽奖次数的限制。 2.长轮询

网友评论

    本文标题:Apollo(2) 长轮询

    本文链接:https://www.haomeiwen.com/subject/avcnfdtx.html