写点什么

Nacos 配置中心之动态感知

作者:周杰伦本人
  • 2022 年 8 月 06 日
  • 本文字数:1954 字

    阅读完需:约 6 分钟

Nacos 配置中心之动态感知

我们通过控制台或 API 的方式修改了配置后,如何实时通知?


这里利用到了事件处理机制,配置文件被修改后调用了 nacos 服务端的/v1/cs/configs 接口,接口中发布了 ConfigDataChangeEvent 事件

LongPollingService 监听事件类

LongPollingService 继承 AbstractEventListener,AbstractEventListener 是事件抽象类,它有一个 onEvent 抽象方法,而 LongPollingService 实现了这个方法


@Overridepublic void onEvent(Event event) {    if (isFixedPolling()) {        // ignore    } else {        if (event instanceof LocalDataChangeEvent) {            LocalDataChangeEvent evt = (LocalDataChangeEvent)event;            scheduler.execute(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps));        }    }}
复制代码


LongPollingService 可以看到 LocalDataChangeEvent 事件,这个事件是服务端的配置数据发生变化时发布的一个事件。


onEvent 方法中通过线程池来执行一个 DataChangeTask 任务

DataChangeTask 线程

DataChangeTask 是一个线程,实现了 Runnable 接口,对应的 run()如下:


class DataChangeTask implements Runnable {    @Override    public void run() {        try {            ConfigService.getContentBetaMd5(groupKey);            for (Iterator<ClientLongPolling> iter = allSubs.iterator(); iter.hasNext(); ) {                ClientLongPolling clientSub = iter.next();                if (clientSub.clientMd5Map.containsKey(groupKey)) {                    // 如果beta发布且不在beta列表直接跳过                    if (isBeta && !betaIps.contains(clientSub.ip)) {                        continue;                    }
// 如果tag发布且不在tag列表直接跳过 if (StringUtils.isNotBlank(tag) && !tag.equals(clientSub.tag)) { continue; }
getRetainIps().put(clientSub.ip, System.currentTimeMillis()); iter.remove(); // 删除订阅关系 LogUtil.clientLog.info("{}|{}|{}|{}|{}|{}|{}", (System.currentTimeMillis() - changeTime), "in-advance", RequestUtil.getRemoteIp((HttpServletRequest)clientSub.asyncContext.getRequest()), "polling", clientSub.clientMd5Map.size(), clientSub.probeRequestSize, groupKey); clientSub.sendResponse(Arrays.asList(groupKey)); } } } catch (Throwable t) { LogUtil.defaultLog.error("data change error:" + t.getMessage(), t.getCause()); } }
DataChangeTask(String groupKey) { this(groupKey, false, null); }
DataChangeTask(String groupKey, boolean isBeta, List<String> betaIps) { this(groupKey, isBeta, betaIps, null); }
DataChangeTask(String groupKey, boolean isBeta, List<String> betaIps, String tag) { this.groupKey = groupKey; this.isBeta = isBeta; this.betaIps = betaIps; this.tag = tag; }
final String groupKey; final long changeTime = System.currentTimeMillis(); final boolean isBeta; final List<String> betaIps; final String tag;}
复制代码


  1. 遍历 allSubs 中的客户端长轮询请求。

  2. 比较每个客户端长轮询请求携带的 groupKey,如果服务端变更的配置和客户端请求关注的配置一致,则直接返回,调用 clientSub.sendResponse()方法将变更信息返回

总结

现在大家明白为什么 nacos 会进行实时动态感知,大体流程就是当在配置中心修改配置后,会发布事件 ConfigDataChangeEvent,EventDispatcher 触发事件,通知监听者,LongPollingService 就是监听者之一,它要做的操作就是通过线程池开启定时线程,线程中遍历客户端的所有长轮询的请求,对比客户端携带的 groupKey,与服务端变更的 groupKey 就返回客户端变更信息,从而实现客户端的动态感知


这就是 Nacos 配置中心的动态感知的原理,基于事件监听机制实现,大家知道了吗,喜欢的朋友们欢迎在评论区留言或提出不同意见。这样的话我们对 nacos 源码的解读差不多就到这里了,包括它的两大模块,注册中心和配置中心,后续我们讲解一下 RocketMQ 的知识,RocketMQ 在如今微服务畅行的环境之下也是一个非常重要的技术点,接下来跟着我一起学习吧~

发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2020.02.29 加入

公众号《盼盼小课堂》,多平台优质博主

评论

发布
暂无评论
Nacos配置中心之动态感知_8月月更_周杰伦本人_InfoQ写作社区