Nacos 客户端配置更新机制

Nacos 作为配置中心,在配置文件被更新之后,客户端如何知道服务端已经有内容变动了呢?

这篇文章重点分析和学习这个机制。

初始化NcosManager

Nacos 客户端在启动的时候,首先初始化 NacosConfigManager 类。

	@Bean
	public NacosConfigManager nacosConfigManager(
			NacosConfigProperties nacosConfigProperties) {
		return new NacosConfigManager(nacosConfigProperties);
	}

创建ConfigService

NacosConfigManager 初始化的过程中,接着创建 ConfigService 类。

public static ConfigService createConfigService(Properties properties) {
       Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
       Constructor constructor = driverImplClass.getConstructor(Properties.class);
       ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);
       return vendorImpl;
}

创建 ClientWorker

ConfigService 通过构造函数创建对象的时候,接着创建了 ClientWorker 对象。到现在为止,我们才发现 ClientWorker 是真正干活的对象。

ClientWorker 对初始化自己的时候,启动了一个异步线程,默认是每隔五秒钟向 Nacos 服务器拉取一次配置信息。

public void startInternal() {
   executor.schedule(() -> {
       while (!executor.isShutdown() && !executor.isTerminated()) {
           try {
               listenExecutebell.poll(5L, TimeUnit.SECONDS);
               if (executor.isShutdown() || executor.isTerminated()) {
                   continue;
               }
               executeConfigListen();
           } catch (Exception e) {
               LOGGER.error("[ rpc listen execute ] [rpc listen] exception", e);
           }
       }
   }, 0L, TimeUnit.MILLISECONDS);
   
}

这是一个无限循环的任务,只要线程池不中断或者退出,会一直请求下去。具体是如何做到无线循环的,可以在接下来的步骤中看到。

向服务器发请求,拉取配置信息

RpcClient#request,客户端在3秒时间内,重试3次向服务器拉取最新的配置信息。

while (retryTimes < RETRY_TIMES && System.currentTimeMillis() 
	< timeoutMills + start) {
 //
}

如果成功拉取到配置信息,开始循环遍历,服务端哪些 Key 的属性值发生了变化。

刷新内容和检查

如果刚才有 key 属性值发生了变化,拿着这些变化的 Key 向服务端发送请求,拉取最新的内容,超时时间为3秒。ClientWorker#refreshContentAndCheck。

ConfigResponse response = getServerConfig(cacheData.dataId, cacheData.group, cacheData.tenant, 3000L,notify);
cacheData.setContent(response.getContent());
cacheData.setEncryptedDataKey(response.getEncryptedDataKey());
if (null != response.getConfigType()) {
    cacheData.setType(response.getConfigType());
}
cacheData.checkListenerMd5();

注册Nacos 监听事件

接下来又开启了一个异步线程,为当前客户端注册 NacosContextRefresher#registerNacosListener 监听器。

这个监听器负责发布服务端键值对更新的事件。

private void registerNacosListener(final String groupKey, final String dataKey) {
	applicationContext.publishEvent(
								new RefreshEvent(this, null, "Refresh Nacos config"));
}

最终,负责监听这个事件的 RefreshEventListener 在接收到事件变化之后,将发生变化的 Key 打印出来,通知客户端 Nacos 服务端配置信息发生了变化。

	public void handle(RefreshEvent event) {
		if (this.ready.get()) { // don't handle events before app is ready
			log.debug("Event received " + event.getEventDesc());
			Set<String> keys = this.refresh.refresh();
			log.info("Refresh keys changed: " + keys);
		}
	}

总结,Nacos 服务端配置信息发生了变更之后,不是由服务端推送给客户端的。正确的理解是这个样子,客户端定时向服务端循环发送请求,拉取服务端配置信息,如果有变更,就自动更新自己的值为最新值。

Nacos 为什么要设置成客户端拉取服务端配置信息呢?因为 Nacos 客户端和服务端维持的是短链接,有超时时间,时间过了之后,链接会自动断开,无法获取服务端信息。

如果使用长链接的话,连接的客户端很多,会对客户端造成一定压力。

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值