Nacos配置中心核心源码
2024-12-06 10:17:36 0 举报
Nacos配置中心核心执行流程
作者其他创作
大纲/内容
readFile(localPath)
遍历读取结果,将每个配置文件dump到磁盘
@Bean
/v1/cs/configs
遍历订阅者将事件通知给订阅者
ConfigController#getConfig
基于队列数据构造一个AysncTask,提交到线程池执行调用集群每个节点的配置信息变动通知API
ProcessRunnable
processor.process(task)
发布RefreshEvent
sendResponse(changedGroups)
向Nacos Server发起一个长连接,30s超时返回Nacos Server有更新过的dataIds
2、初始化另外一个线程池核心线程数:处理器核数
/v1/cs/configs/listener
给LocalDataChangeEvent事件注册一个事件订阅者,监听Nacos发布的本地数据变动的Nacos事件
HTTP
如果subscribe有配置线程池,则异步执行,否则同步执行
NacosConfigBootstrapConfiguration
通过MetricsHttpAgent#httpPost调用服务端APIreadTimeoutMs:45sLong-Pulling-Timeout:30sLong-Pulling-Timeout-No-Hangup:true
this.executorService = Executors .newScheduledThreadPool
1、初始化一个只有一个核心线程线程的线程池
获取配置信息中发生变化的配置参数key
nacosContextRefresher
ExternalDumpService#init
发送响应给客户端
int listenerSize = cacheMap.size()
向线程池提交一个一次性任务,延迟29.5s执行
checkUpdateConfigStr
NacosConfigService#getConfigInner
NacosConfigService
ContextRefresher#refreshEnvironment
在SpringBoot应用启动时会发布相关事件,监听到这个事件后,为Nacos的dataId注册监听器,当Nacos配置被修改后,对应的监听器会被调用,在这个监听器中会发布RefreshEvent,来刷新配置和应用
task = removeTask(taskKey)
发起远程调用
Runnable
处理事件
创建ConfigService
NotifyCenter.publishEvent(event)
返回该dataId给客户端
listeners.running(context)
ConfigCacheService.dump
locator.locateCollection(environment)//locator是PropertySourceLocator
run
openEventHandler()
NotifySingleTask task = queue.poll()
allSubs.remove(ClientLongPolling.this)
将对应配置文件的全部内容写入数据库
标记了@Service注解,这是Spring中的一个Bean
allSubs.add(this)
读取配置信息
http://ip:端口/nacos/v1/cs/communication/dataChange?dataId=tech-pay.yaml&group=DEFAULT_GROUP
加载扩展配置
spring.cloud.nacos.config.extension-configs
创建一个DataChangeTask提交到线程池执行
NacosConfigManager//持有 ConfigService//持有 NacosConfigProperties
刷新标记了RefreshScope注解的Bean
agent .httpPost(Constants.CONFIG_CONTROLLER_PATH + \"/listener\
构造函数
LocalConfigInfoProcessor.saveSnapshot
AbstractSharedListener#receiveConfigInfo
获取本地容错文件
receiveEvent(event)
取出DumpTask
dumpOperate
NacosPropertySourceLocator#loadNacosPropertySource
对更新过配置信息的datatId,调用Nacos Server API获取配置信息,更新本地快照
将获取的事件通知给订阅者处理
NacosConfigAutoConfiguration
service = NacosFactory.createConfigService(nacosConfigProperties.assembleConfigServiceProperties())
从本地磁盘文件读取配置信息
取出任务队列中的通知任务
监听配置更新的长轮询任务
ConfigFileApplicationListener#onApplicationEvent
RefreshEventListener
通过反射创建NacosConfigService
如果MD5值发生过变化,调用监听器
PropertySourceBootstrapConfiguration#initialize
handle((RefreshEvent) event)
this.agent = new MetricsHttpAgent(new ServerHttpAgent(properties)); this.agent.start()
GET请求
CommunicationController#notifyConfigInfo
DiskUtil#clearAll
加载共享配置spring.cloud.nacos.config.shared-configs
HTTP POST调用长轮询API
DataChangeTask
subscriber.onEvent(event)
3、通过第一个线程池运行一个延迟调度的定时任务
response.setHeader(\"Pragma\
销毁Bean后,下次使用Bean时会通过BeanFactory重新生产这个Bean,将会使用新的配置参数
计算配置文件内容的MD5
监听SpringBoot启动时发布的ApplicationReadyEvent
分页查询Mysql config_info表的配置数据,一个配置文件对应一行数据
clientSub.sendResponse(Arrays.asList(groupKey))
执行任务
NotifyCenter.registerSubscriber(new Subscriber()
groupKey:tech-pay.yaml+DEFAULT_GROUP+devmd5: 配置文件内容对应的MD5值lastModifiedTs:最后更新时间
从队列中移除当前任务
销毁Bean
NacosPropertySourceLocator#locate
MetricsHttpAgent#httpGet
短轮询
EventPublishingRunListener#environmentPrepared
Nacos延迟任务执行引擎
为了提升稳定性和降低数据库压力,配置信息是在本地磁盘文件读取的,所以直接修改MySql中配置这里并不生效。当发布ConfigDataChangeEvent的事件时会更新本地内存和磁盘文件
clientMd5Map = MD5Util.getClientMd5Map(probeModify)
for (Iterator<ClientLongPolling> iter = allSubs.iterator(); iter.hasNext(); )
CacheData#checkListenerMd5
任务管理器使用一个Map存放任务,key:tech-pay.yaml+DEFAULT_GROUP
发布本地数据变化的事件
清理本地磁盘文件
LongPollingService
AbstractSharedListener#innerReceive
Nacos配置中心服务端
HttpServletResponse response = (HttpServletResponse) asyncContext.getResponse();
PropertiesPropertySourceLoader#load
Nacos配置中心自动配置类NacosConfigBootstrapConfiguration
SpringApplication.run
是这个LongPollingService
DumpService
loadExtConfiguration(composite)
服务端配置数据更新通知API
RefreshAutoConfiguration
final Event event = queue.take();
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey))
调用初始化器的初始化函数
ClientLongPolling.run时将自身添加到队列allSubs中的
ConfigController#publishConfig
applyInitializers(context)
执行完runner后,发布ApplicationReadyEvent事件
如果内存缓存不存在该MD5值,则将该配置文件写入到本地磁盘
创建 MetricsHttpAgent用来向Nacos服务端发起HTTP请求的代理
如果是Nacos集群轮询选择一个服务节点调用
匿名Runnable
NacosPropertySourceLocator
获取HttpServletResponse
ConfigController#listener
开始执行长轮询或短轮询inner为ConfigServletInner
registerNacosListenersForApplications
如果存在容错文件
将内存缓存的需要刷新的配置文件,按照3000个分为一组为每个组创建一个LongPollingRunnable提交到线程池,监听配置更新一个分组只提交一次任务
NacosRestTemplate#get
把事件放入阻塞队列
检查变更的配置文件,返回变化的配置文件列表
触LocalDataChangeEvent发事件,调用注册的匿名的Subscriber的onEvent
isRefreshEnabled()//默认是true
checkLocalConfig(cacheData)
int longingTaskCount = (int) Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize())
刷新环境配置信息
listener.receiveConfigInfo(contentTmp)
executorService.execute(this)
将变化的文件列表响应给客户端
createConfigService(nacosConfigProperties)
将文件内容的MD5缓存到内存,用于判断文件是否存在
loadSharedConfiguration(composite)
如果监听的所有dataId的配置内容都没有变化
将当前请求转换为异步请求
更新配置信息
dumpConfigInfo(dumpAllProcessor)
Nacos启动自动Dump数据库配置信息到服务端本地磁盘文件
当Nacos基于长轮询机制感知到配置更新时会回调Nacos的Listener这里注册的监听器类型是:AbstractSharedListener
ConfigDataChangeEvent事件对应的subscriber订阅者类型是:AsyncNotifyService的内部创建的一个Subscriber实例NotifyCenter.registerSubscriber(new Subscriber() { @Override public void onEvent(Event event) {
AsyncTask
LongPollingRunnable
通过属性源定位器从外部配置中心获取配置,添加到Spring环境中
NacosPropertySourceBuilder#build
ConfigService configService = nacosConfigManager.getConfigService()
DefaultPublisher#publish
通过比对MD5判断文件是否发生变化
this.executor = Executors.newScheduledThreadPool
把任务添加到转储任务管理器
执行长轮询
为nacos的dataId注册Nacos监听器
加载顺序:1、文件名2、文件名.扩展名3、文件名-profile.扩展名优先级:3>2>1
每10ms执行一次
使用配置文件数量除以3000得到分组数量
Spring的扩展点之一,常用于Web应用初始化上下文,例如根据上下文环境注册属性源,激活配置文件等
this.queue.offer(event)
/nacos/v1/cs/communication/dataChange
checkConfigInfo
检查本地容错配置
@PostConstruct
persistService.findAllConfigInfoFragment
客户端pull长轮询,出现异常延迟2s执行
ClientWorker#getServerConfig
运行提交的任务
ApplicationContextInitializer
通过零拷贝技术,将文件内容拷贝到Response输出流
Listener#receiveConfigInfo
clientSub.clientMd5Map.containsKey(groupKey)
ConfigServletInner.doGetConfig
加载应用配置
触发LocalDataChangeEvent事件
启动SpringBoot应用
Thread
发布配置数据变化的Nacos事件
executeAsyncInvoke
SpringBoot提供的加载配置文件的接口
Nacos配置中心自动配置类
ClientLongPolling
ConfigService
this.executor.scheduleWithFixedDelay(new Runnable() { @Override public void run() { try { checkConfigInfo(); } catch (Throwable e) { LOGGER.error(\"[\" + agent.getName() + \"] [sub-check] rotate check error\
通过RestTemplate调用任务对应集群节点的api进行通知
将当前任务ClientLongPolling添加到队列有一个客户端请求会创建一个并添加队列中,29.5s开始执行最后的配置比对前移除
RefreshEventListener#onApplicationEvent
循序在阻塞队列上取事件
Collection<Member> ipList = memberManager.allMembers()
NacosPropertySourceLocator#loadNacosDataIfPresent
获取Nacos集群服务实例列表
到数据库查询配置信息
onEvent(Event event)
NacosPropertySourceBuilder#loadNacosData
clientSub是ClientLongPolling,如果它长轮询监听的配置文件Map包含触发事件的配置文件dataId
processor是DumpProcessor
创建ClientWorker客户端工作类
for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) { // The task list is no order.So it maybe has issues when changing. executorService.execute(new LongPollingRunnable(i)); }
如果有dataId列表不为空,也就是有dataId的配置内容发生了变化返回结果给客户端
this.context.publishEvent(new RefreshScopeRefreshedEvent())
ServerHttpAgent#httpGet
DumpConfigHandler.configDump(build.build())
extract(this.context.getEnvironment().getPropertySources())
Dump配置文件到本地磁盘更新配置内容对应的MD5到内存发布LocalDataChangeEvent
配置中心核心接口
获取配置中心服务ConfigService
dumpService.dump
ContextRefresher#refresh
为集群每个节点创建一个通知任务,添加到任务队列(包含当前节点)
构造函数,使用延迟调度的线程池创建一个延迟调度的定时任务
机器心跳间隔超6小时全量转储,否则增量转储
processTasks
GET
listeners.environmentPrepared(environment)
CacheData#safeNotifyListener
为每个分组,创建一个长轮询任务,提交到线程池运行,监听配置更新
RefreshScope#refreshAll
DumpAllProcessor#process
调用服务端配置信息更新通知API
发布环境变更事件并带上变化的参数key
添加刷新记录
将变动的配置数据添加到队列
解析客户端参数得到需要监听的配置Mapkey:dataId(实际为dataId+group)val:此时客户端该配置文件配置内容的MD5
根据获取的配置信息,更新缓存的配置信息和MD5
cacheData.setUseLocalConfigInfo(true)
PropertySourceLoader
DefaultPublisher
final AsyncContext asyncContext = req.startAsync();
onApplicationEvent(ApplicationReadyEvent event)
NacosDelayTaskExecuteEngine
向线程池提交下一轮长轮询任务
服务端发布配置API
全量转存(如果是增量转储会校验dataId的配置内容MD5发生变化,再为该dataId转储)
长轮询
把客户端请求保存到长轮询执行引擎中
如果本地没有获取到配置信息,则远程调用配置中心获取配置
获取之前的配置信息
Nacos自动配置类
GenericScope#destroy()
ExternalDumpService
和获取配置调用的是同一个Nacos Server API
请求头中Long-Pulling-Timeout参数不为空,执行长轮询,否则短轮询
对比最新配置的MD5和CacheData之前记录的MD5
addConfigFilesToEnvironment
Class<?> driverImplClass = Class.forName(\"com.alibaba.nacos.client.config.NacosConfigService\"); Constructor constructor = driverImplClass.getConstructor(Properties.class); ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);
SpringCloud 监听器监听该事件
服务端长轮询API
收藏
0 条评论
下一页