Nacos2的定时刷新机制

如下分析基于nacos-client-2.2.4。
Nacos的定时刷新是在客户端实现的,具体来说是在com.alibaba.nacos.client.config.impl.ClientWorker类中。
ClientWorker的构造函数中实例化了一个ScheduledExecutorService定时任务线程池,该定时任务线程池用于执行定时登录操作和启动定时刷新配置信息操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public ClientWorker(final ConfigFilterChainManager configFilterChainManager, ServerListManager serverListManager,
final NacosClientProperties properties) throws NacosException {
this.configFilterChainManager = configFilterChainManager;

init(properties);

agent = new ConfigRpcTransportClient(properties, serverListManager);
int count = ThreadUtils.getSuitableThreadCount(THREAD_MULTIPLE);
// 实例化定时任务线程池
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(Math.max(count, MIN_THREAD_NUM),
r -> {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker");
t.setDaemon(true);
return t;
});
agent.setExecutor(executorService);
agent.start();

}

并将该定时任务线程池作为com.alibaba.nacos.client.config.impl.ConfigTransportClientexecutor属性。
com.alibaba.nacos.client.config.impl.ConfigTransportClientstart()方法中,启动了定时登录任务和定时获取配置信息的操作。

1
2
3
4
5
6
7
public void start() throws NacosException {
securityProxy.login(this.properties);
// 通过定时任务执行登录操作
this.executor.scheduleWithFixedDelay(() -> securityProxy.login(properties), 0,
this.securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS);
startInternal();
}

com.alibaba.nacos.client.config.impl.ClientWorker.$ConfigRpcTransportClientstartInternal()方法中,通过一个while循环启动了一个定时刷新配置的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void startInternal() {
executor.schedule(() -> {
while (!executor.isShutdown() && !executor.isTerminated()) {
try {
// 通过从BlockingQueue队列中获取元素的等待时间实现定时刷新,间隔时长:5s
listenExecutebell.poll(5L, TimeUnit.SECONDS);
if (executor.isShutdown() || executor.isTerminated()) {
continue;
}
executeConfigListen();
} catch (Throwable e) {
LOGGER.error("[rpc listen execute] [rpc listen] exception", e);
try {
Thread.sleep(50L);
} catch (InterruptedException interruptedException) {
//ignore
}
notifyListenConfig();
}
}
}, 0L, TimeUnit.MILLISECONDS);

}

每隔5秒钟就会执行com.alibaba.nacos.client.config.impl.ClientWorker.$ConfigRpcTransportClientexecuteConfigListen()方法检查并获取最新配置的操作,更加具体地说,是在com.alibaba.nacos.client.config.impl.ClientWorker.$ConfigRpcTransportClientcheckListenCache()方法中检查并刷新配置信息的,完整的执行活动图如下所示。

当我们在属性中使用了注解@NacosValue并将autoRefreshed属性设置为true,在应用启动时会将这些使用了@NacosValue注解的属性信息保存在NacosValueAnnotationBeanPostProcessorplaceholderNacosValueTargetMap属性集合中,当在com.alibaba.nacos.client.config.impl.ClientWorker中通过定时任务检测到属性的配置内容有更新时就会使用Spring事件机制发布通知,并在NacosValueAnnotationBeanPostProcessoronApplicationEvent方法中完成对属性内容的更新。

1
2
3
// 使用注解实现配置内容的动态更新
@NacosValue(value = "${user.id}", autoRefreshed = true)
private String userId;
1
2
3
4
5
6
7
8
9
10
11
// NacosValueAnnotationBeanPostProcessor.java
@Override
public void onApplicationEvent(NacosConfigReceivedEvent event) {
// In to this event receiver, the environment has been updated the
// latest configuration information, pull directly from the environment
// fix issue #142
for (Map.Entry<String, List<NacosValueTarget>> entry : placeholderNacosValueTargetMap
.entrySet()) {
// 在这里使用反射机制实现属性内容的动态更新
}
}