Nacos 1.4.x 配置管理交互 与 源码简解
以一次 配置推送 解析整个交互过程,理解 Nacos 配置管理的架构;
背景知识:长轮训 long-polling,仅需此一遭便可理解。
1. Nacos-0 处理 long-polling 的过程,holding 时会放入 queue,等候 LocalDataChangeEvent 通知并处理变更配置(告知客户端)
2. Nacos-1 处理 publish-config 的过程,先写数据库,再发出一个 ConfigDataChangeEvent ,再由 AsyncTask 告知 all Members
3. 处理 DumpTask 的过程,主要是把 数据库为准 的配置 dump 入 DiskFile and MemoryCache
a. 然后发布一个事件 LocalDataChangeEvent ,转而告知了 (1)
4. Nacos-2 处理 get-config 的过程,先读 MemoryCache 匹配并获取配置信息,配置内容在 DiskFile 直接 channel.transfer 返回
针对 AsyncTask 通知所有集群成员 (包括自己)
好处是更平等地对待集群内的所有成员,这样发起者自身在处理 DumpTask 不至于提前太多;
若本地内优先处理,由于 LocalDataChangeEvent 让 客户端 长轮训 返回,客户端发起配置获取时,存在延时 其他节点 尚未 DumpTask 结束,所以会拿到旧配置;
然后再发起 long-polling 才可能感知到 md5 有变化而获取到最新配置;
最糟糕情况是还没 DumpTask 结束,要 30s 超时后才获得最新变更。
## 简解源码 > 走读
注:... 表示异步执行,* 标识重点
### Long-polling .getConfigChange
ConfigController.listener() // The client listens for configuration changes.ConfigServletInner.doPollingConfig()LongPollingService.addLongPollingClient()... ClientLongPolling.run()create ScheduledFuture: asyncTimeoutFuture // timeout with return nullQueue<ClientLongPolling> allSubs.add(ClientLongPolling.this);... **LocalDataChangeEvent** *// 关键的配置变更事件*... DataChangeTask.run()Queue<ClientLongPolling> allSubs.iterator() // compare and return changeGroupKeys
### Publish config .change Config
ConfigController.publishConfig() // Adds or updates non-aggregated data.**PersistService.insertOrUpdate()** *// write into db first***NotifyCenter.publishEvent > ConfigDataChangeEvent** *// 关键配置变更事件*... AsyncNotifyService.onEvent()ConfigExecutor.executeAsyncNotify(new AsyncTask(nacosAsyncRestTemplate, queue)) // async task in queue... AsyncTask.run() executeAsyncInvoke()restTemplate url:(**/v1/cs/communication/dataChange**) // rest get url to notify all members.
#### Notify data change // all members.
CommunicationController.notifyConfigInfo()DumpService.dump()TaskManager.addTask(taskKey, new DumpTask(..))... DumpProcessor.process()**PersistService.findConfigInfo()** *// get config from db*DumpConfigHandler.configDump(ConfigDumpEvent)DumpConfigHandler.configDump()ConfigCacheService.dump()**DiskUtil.saveToDisk(dataId, group, tenant, content)** *// dump in disk first*ConfigCacheService.updateMd5()MemoryCache.update() *// dump in memory second*NotifyCenter.publishEvent > **LocalDataChangeEvent** *// 关键的配置变更事件*
