nacos配置中心动态刷新原理分析(server端)

目录

      一、背景介绍

      二、侦听客户端长轮询

      三、服务端推送变更配置


一、背景介绍

在之前上一篇文章中我们一起看了nacos配置中心动态刷新client端的长轮询逻辑监听、事件发布变更配置和client端怎么和SpringBoot整合。

所以,本篇我们主要来看nacos服务端是怎么处理客户端长轮询监听配置变更和主动推送变更配置的。

二、侦听客户端长轮询

从上一篇中我们知道nacos客户端在长轮询逻辑中通过checkUpdateDataIds()方法发出http请求到服务端探测是否有配置发生变更。

// check server config
List<String> changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList);
if (!CollectionUtils.isEmpty(changedGroupKeys)) {
    LOGGER.info("get changedGroupKeys:" + changedGroupKeys);
}

在checkUpdateDataIds()底层我们能够发现调用服务端的地址链接是/v1/cs/configs/listener。

HttpRestResult<String> result = agent
    .httpPost(Constants.CONFIG_CONTROLLER_PATH + "/listener", headers, params, agent.getEncode(),
        readTimeoutMs);

所以,我们直接看nacos服务端/v1/cs/configs/listener对应的方法。

@PostMapping("/listener")
@Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class)
public void listener(HttpServletRequest request, HttpServletResponse response) throws IOException {
    request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
    String probeModify = request.getParameter("Listening-Configs");
    if (StringUtils.isBlank(probeModify)) {
        throw new IllegalArgumentException("invalid probeModify");
    }
    probeModify = URLDecoder.decode(probeModify, Constants.ENCODE);
    Map<String, String> clientMd5Map;
    try {
        //计算 MD5 值
        clientMd5Map = MD5Util.getClientMd5Map(probeModify);
    } catch (Throwable e) {
        throw new IllegalArgumentException("invalid probeModify");
    }
    // 进行长轮询逻辑
    inner.doPollingConfig(request, response, clientMd5Map, probeModify.length());
}

该方法前面都是一些校验以及生成clientMd5Map,这个Map里面包含了监听配置变更的key以及value,下面会用到,核心主要看inner.doPollingConfig()这个逻辑。

public void doPollingConfig(HttpServletRequest request, HttpServletResponse response,
                            Map<String, String> clientMd5Map, int probeRequestSize) throws IOException {
    //长轮询
    if (LongPollingService.isSupportLongPolling(request)) {
        longPollingService.addLongPollingClient(request, response, clientMd5Map, probeRequestSize);
        return;
    }
    // 兼容短轮询逻辑.
    List<String> changedGroups = MD5Util.compareMd5(request, response, clientMd5Map);
    // 兼容短轮询结果.
    String oldResult = MD5Util.compareMd5OldResult(changedGroups);
    String newResult = MD5Util.compareMd5ResultString(changedGroups);
    String version = request.getHeader(Constants.CLIENT_VERSION_HEADER);
    if (version == null) {
        version = "2.0.0";
    }
    int versionNum = Protocol.getVersionNumber(version);
    // Befor 2.0.4 version, return value is put into header.
    if (versionNum < START_LONG_POLLING_VERSION_NUM) {
        response.addHeader(Constants.PROBE_MODIFY_RESPONSE, oldResult);
        response.addHeader(Constants.PROBE_MODIFY_RESPONSE_NEW, newResult);
    } else {
        request.setAttribute("content", newResult);
    }
    Loggers.AUTH.info("new content:" + newResult);
    // Disable cache.
    response.setHeader("Pragma", "no-cache");
    response.setDateHeader("Expires", 0);
    response.setHeader("Cache-Control", "no-cache,no-store");
    response.setStatus(HttpServletResponse.SC_OK);
}

该方法首先判断客户端发送过来的请求是长轮询还是短轮询,如果是长轮询直接执行长轮询逻辑然后return,下面的逻辑是兼容短轮询的逻辑实现。

在兼容的短轮询逻辑中拿到刚才的clientMd5Map进行解析、比对是否和服务端发生了变更,如果发生了变更就将老数据和新数据都放到响应的header里面,直接返回给nacos客户端了。

是否是长轮询其实就是判断请求头中是否设置了Long-Pulling-Timeout,刚才在ClientWorker的请求头中设置了这个参数。

确定是长轮询逻辑,我们直接看addLongPollingClient()添加客户长轮询这个逻辑。

public void addLongPollingClient(HttpServletRequest req, HttpServletResponse rsp, Map<String, String> clientMd5Map, int probeRequestSize) {
    ......
    int delayTime = SwitchService.getSwitchInteger(SwitchService.FIXED_DELAY_TIME, 500);

    //为 LoadBalance 添加延迟时间,并提前 500ms 返回响应,避免客户端超时(即超时时间减 500ms 后赋值给 timeout 变量)
    long timeout = Math.max(10000, Long.parseLong(str) - delayTime);
    //判断是否为固定轮询,是则 30s 后执行;否则 29.5s 后执行
    if (isFixedPolling()) {
        timeout = Math.max(10000, getFixedPollingInterval());
        //除了设置修复轮询超时之外什么都不做
    } else {
        long sta
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值