Nacos配置中心之动态感知
我们通过控制台或API的方式修改了配置后,如何实时通知?
这里利用到了事件处理机制,配置文件被修改后调用了nacos服务端的/v1/cs/configs接口,接口中发布了ConfigDataChangeEvent事件
LongPollingService 监听事件类
LongPollingService继承AbstractEventListener,AbstractEventListener是事件抽象类,它有一个onEvent抽象方法,而LongPollingService实现了这个方法
@Override
public 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;
}
- 遍历allSubs中的客户端长轮询请求。
- 比较每个客户端长轮询请求携带的groupKey,如果服务端变更的配置和客户端请求关注的配置一致,则直接返回,调用clientSub.sendResponse()方法将变更信息返回
总结
现在大家明白为什么nacos会进行实时动态感知,大体流程就是当在配置中心修改配置后,会发布事件ConfigDataChangeEvent,EventDispatcher触发事件,通知监听者,LongPollingService就是监听者之一,它要做的操作就是通过线程池开启定时线程,线程中遍历客户端的所有长轮询的请求,对比客户端携带的groupKey,与服务端变更的groupKey就返回客户端变更信息,从而实现客户端的动态感知
这就是Nacos配置中心的动态感知的原理,基于事件监听机制实现,大家知道了吗,喜欢的朋友们欢迎在评论区留言或提出不同意见。这样的话我们对nacos源码的解读差不多就到这里了,包括它的两大模块,注册中心和配置中心,后续我们讲解一下RocketMQ的知识,RocketMQ在如今微服务畅行的环境之下也是一个非常重要的技术点,接下来跟着我一起学习吧~