栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

Nacos-配置监听

Nacos-配置监听

前言

本以为这是个简单的问题,后来细看,这个问题不是抽完半包烟估计是看不出来的!源码调试环境和之前的有些不同,客户端实现配置中心需要添加额外依赖!如下!

		
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
            2.1.0.RELEASE
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-config
            2.1.0.RELEASE
        

最好保持一致的版本,至于怎么配置情况往期文章Nacos作为服务配置中心这里版本请保持我上面配置的!那么还是原来的流程,上http接口!

这个是获取配置详情的!

这个是监听配置变化的,注意这里使用的是长轮询,并不是长链接,这里我发现阿里的中间件比较喜欢使用长轮询的方式,看过RocketMQ的朋友应该也知道RocketMQ使用的也是长轮询的机制获取消息的!由于Nacos-客户端配置中心比较复制,而且有多个监听,这里就不以之前分析服务注册和心跳机制那样一条线写下来了,而是分为多条线来写,这里多条线有些事并行,但是也是有启动顺序的,这让文章也稍微好写一点!

主线程初始化

简单介绍
这个线程只要就两个功能,第一个是开启一个10毫秒的定时任务,第二个就是将Nacos中对应的配置拉到本地目录,稍微简单点,不像其他监听线程,乱的一逼!

启动入口

这个是SpringCloudContext牵引加载的
进入locate方法

第一块代码进入后流程如下!

加载Nacos配置中心

进入NacosConfigService

NacosConfigService构造方法的代码如下:

初始化一个HttpAgent,这里有调用装饰器模式,实际工作的类是ServerHttpAgent,MetricsHttpAgent内部也调用了ServerHttpAgent的方法,增加了监控统计信息ClientWorker是一个客户端的一个工作类,agent作为参数传入ClientWorker,可以基本猜测到里面会用到agent做一些远程调用相关的事情!

这里ClientWorker创建是一个比较核心的方法!

切入ClientWorker

这里有三块比较重要的代码块,我们逐个分析!

第一块是创建一个线程池,executor这个线程池是用来检查配置的第二块也是创建了一个线程池,但是目前并没有直接使用到,executorService这个线程主要是用于实现客户端定时长轮询的,也就是长轮询监听Nacos服务端配置变化的!第三块就是使用executor线程池开启一个定时任务,每隔10毫秒,执行checkConfigInfo();方法,检查一次配置信息

这里checkConfigInfo();方法比较有意思,也比较恶心!我们切入checkConfigInfo();方法!

深入checkConfigInfo();方法

cacheMao:用来存储监听变更的缓存集合,key是根据dataId/group/tenant(租户)拼接的值,value是对应存储在Nacos服务器上的配置文件内容长轮询任务拆分:默认情况下,每个长轮询LongPollingRunnable任务处理3000个监听配置集,如果超过3000个,则需要启动多个LongPollingRunnable去执行

不幸的是这里服务刚开始启动,走到这里并不会进入这个if判断,也就是下面这部分代码根本不会执行

			for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) {
                // 要判断任务是否在执行 这块需要好好想想。 任务列表现在是无序的。变化过程可能有问题
                executorService.execute(new LongPollingRunnable(i));
            }
            currentLongingTaskCount = longingTaskCount;

原因是currentLongingTaskCount的初始值是0,cacheMap的size也是0,所以这里的if进入逻辑不会执行,这里也就是每隔10毫秒执行到if后从新在执行,一致等待if判断条件准入!第一块代码就分析到这里,我们回到下面这个地方,开始分析第二块逻辑

进入loadApplicationConfiguration方法

loadApplicationConfiguration这个方法中调用了loadNacosDataIfPresent,然后又循环调用loadNacosDataIfPresent,这里第一次调用dataId为server-consumer.yaml,第二次则是加了激活环境的,也就是server-consumer-dev.yaml
注意这里如果Nacos服务端没有添加对应配置文件,那么下面执行远程http请求Nacos服务的时候会404

直接切入loadNacosDataIfPresent方法

深入build方法

调用loadNacosData方法

直接进入getConfigInner方法

这个方法其实逻辑比较简单,就是从本地配置,本地配置不是客户端程序内存 等下进去各位就知道了,从本地配置中获取配置内容,如果不为空,那么第二块逻辑直接返回,如果为空那么
交给第三块逻辑发起远程请求从Nacos服务端获取对应配置

worker.getServerConfig(dataId, group, tenant, timeoutMs);

深入LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);方法

这个LocalConfigInfoProcessor类建议先大致过一遍,就知道我刚才为什么标注红色的字体说不是客户端程序内存,而是本地配置文件!这里操作的就是本地配置文件!文件位于下面这个目录!

注意,客户端程序刚启动的时候是没有这个数据文件的!那么按照代码逻辑,这里会向Nacos服务端发起http请求获取对应配置!那么我们进入getServerConfig方法

深入getServerConfig方法
注意这里请求Nacos服务返回的结果是受dataId,group影响的,如果Nacos配置中心中不存在对应的配置,那么返回的状态码就不同!那么这里也就有了switch分支判断!如果对应查询配置不存在,那么就会返回状态码为404

content = worker.getServerConfig(dataId, group, tenant, timeoutMs);



这里请求的接口和文章刚开始列出的Nacos文档中的API对上了!

然后根据http相应信息switch中更具http状态码判断分支逻辑

这里都调用了LocalConfigInfoProcessor.saveSnapshot方法,无非就是最后有个config参数不同,这个参数也就是远程调用Nacos服务返回的配置信息了!

切入saveSnapshot方法

这里有个分支,会根据config是否为null,如果不为空,那么写入本地配置文件,如果为空的话,那么剔除掉文件!那么到这里主线程逻辑就分析完了,

至此,Nacos服务中的配置已经写到本地目录,然后客户端开启了一个10毫秒的线程检查cacheMap的size变化!

触发监听

简单介绍

监听ApplicationReadyEvent事件

当主线任务执行好了后,会发布一个ApplicationReadyEvent事件,那么NacosContextRefresher中就监听了这个事件,那么就会进入NacosContextRefresher的onApplicationEvent方法

进入registerNacosListenersForApplications方法

进入registerNacosListener方法

这里就是构造了Listener,和添加了Listener,进入addListener方法!

调用addTenantListeners方法
调用方法addCacheDataIfAbsent

这个方法有点巧妙!

CacheData cache = getCache(dataId, group, tenant);

getCache其实就是获取cacheMap中的数据,但是这里刚开始是没有值的,因为值还没加载到cacheMap中,还在本地配置文件中

cache = new CacheData(configFilterChainManager, agent.getName(), dataId, group, tenant);

这行代码创建CacheData对象就是读取本地配置文件,这个构造方法如下

loadCacheContentFromDiskLocal方法就是去取本地配置的!最后回到最后那步代码

cacheMap.set(copy);

这行代码可谓是画龙点睛之作,这里往cacheMap中set了值,也就是说改变了cacheMap的size,那么主线程中开启的那个10毫秒的定时任务就会感知到!那么这部分逻辑就结束了

开启监听

触发监听部分也就是改变了cacheMap的大小,然后导致主线程中的定时任务感知到,那么我们把视角切回到主线程中的定时任务!

回看checkConfigInfo方法

这里使用executorService线程次开启了LongPollingRunnable线程任务!

进入LongPollingRunnable线程任务对象
这块代码有点长,挺简单的,我们分块来看

遍历cacheMap检查本地配置!

List changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList);

通过长轮询请求Nacos服务器,检查服务端对应的配置是否发生变更,进入checkUpdateDataIds方法调用checkUpdateConfigStr方法

和文章开头部分监听API对上了

这是30秒的长轮询,如果30秒Nacos服务端查询的配置没有变动,那么返回空,如果30之内任意时间有变动立马返回,如果返回有变化,那么就会得到要获取的配置,通过

 String content = getServerConfig(dataId, group, tenant, 3000L);

getServerConfig和主线程部分的是同一个,逻辑也是一样,获取Nacos配置,然后写入到本地


这一块又是重复执行当前任务!那么基本上到这里真个Nacos客户端获取配置源码就分析完了!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/701555.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号