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 null
Queue<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** *// 关键的配置变更事件*