【Spring Cloud】【Nacos】从源码层面理解Nacos 实现属性动态更新的原理

Nacos 动态刷新配置的原理基于 长轮询机制 和 Spring Cloud Context 的 @RefreshScope 实现。

原理解析

Nacos 配置中心 <-- 长轮询 Nacos 客户端监听到配置变化 --> 触发 Spring Context 的 RefreshEvent
–> RefreshScope` Bean 被重新加载 -->应用中的属性值被动态更新

一、Nacos 客户端监听到配置变化

1.1 启动阶段

通过NacosContextRefresher想nacos注册一个监听器,当有变化的时候,将会发布一个RefreshEvent事件。具体提代码见下:
com.alibaba.cloud.nacos.refresh.NacosContextRefresher#registerNacosListener

		String key = NacosPropertySourceRepository.getMapKey(dataKey, groupKey);
		Listener listener = listenerMap.computeIfAbsent(key,
				lst -> new AbstractSharedListener() {
   
   
					@Override
					public void innerReceive(String dataId, String group,
							String configInfo) {
   
   
					     // ...省略部分代码
					     //向spring发布一个RefreshEvent事件
						applicationContext.publishEvent(
								new RefreshEvent(this, null, "Refresh Nacos config"));
					// ...省略部分代码
					}
				});
		try {
   
   
			configService.addListener(dataKey, groupKey, listener);
		}
		catch (NacosException e) {
   
   
		 // ...省略部分代码
		}

1.2 Nacos 客户端的长轮询

LongPollingRunnable的run方法主要实现功能有,
1、调用nacos服务端接口获取配置项中对应md5值,如果与本地的配置比较有变化则存储为changedGroupKeys
2、对所有的changedGroupKeys获取服务器上最新的配置数据,并更新本地cacheData里面的内容及md5执行
3、执行cacheData.checkListenerMd5(),对有变化的数据通知给启动阶段的注册的监听器

com.alibaba.nacos.client.config.impl.ClientWorker.LongPollingRunnable#run

@Override
        public void run() {
   
   

            List<CacheData> cacheDatas = new ArrayList<CacheData>();
            List<String> inInitializingCacheList = new ArrayList<String>();
            try {
   
   
                // check failover config
                for (CacheData cacheData : cacheMap.get().values()) {
   
   
                    if (cacheData.getTaskId() == taskId) {
   
   
                        cacheDatas.add(cacheData);
                        // ... 省略部分代码
                    }
                }

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

                for (String groupKey : changedGroupKeys) {
   
   
                    String[] key = GroupKey.parseKey(groupKey);
                    String dataId = key[0];
                    String group = key[1];
                    String tenant = null;
                    if (key.length == 3) {
   
   
                        tenant = key[2];
                    }
                    try {
   
   
                        // 获取服务器上最新的配置
                        String[] ct = getServerConfig(dataId, group, tenant, 3000L);
                        CacheData cache = cacheMap.get().get(GroupKey.getKeyTenant(dataId, group, tenant));
                        cache.setContent(ct[0]);
                        // ... 省略部分代码
                }
                for (CacheData cacheData : cacheDatas) {
   
   
                    if (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值