【深入理解SpringCloud微服务】深入理解nacos配置中心(四)——配置新增或修改源码分析
原理回顾
在之前的《宏观理解nacos配置中心原理》这一篇文章中我们已经对nacos的配置新增或修改的流程进行描述。
当我们在nacos-console控制界面上新增或修改了配置并发布后,就会发送http请求,然后nacos服务端接收到http请求后,会进入ConfigController的publishConfig()方法进行处理。
ConfigController的publishConfig()方法先把新增或修改后的配置持久化到MySQL。
配置持久化到MySQL之后,异步进行dump配置内容到磁盘文件以及通知nacos集群中的其他节点发生配置变更。
dump配置内容到磁盘文件是通过DumpService进行的,DumpService先把新增或修改的配置dump到磁盘文件,然后根据文件内容算出一个MD5值,再拿到算出的MD5值与缓存中该配置文件对应的MD5值进行比较,如果两MD5值不一致,说明修改后的配置内容与修改前不一致,也就是发生了配置变更,需要更新MD5值并通知客户端。
源码分析
ConfigController#publishConfig()
@PostMapping
...
public Boolean publishConfig(...) throws NacosException {
...
return configOperationService.publishConfig(configForm, configRequestInfo, encryptedDataKey);
}
ConfigController的publishConfig方法调用configOperationService的publishConfig方法。
ConfigOperationService#publishConfig()
public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequestInfo, String encryptedDataKey)
throws NacosException {
...
// 持久化到MySQL
persistService.insertOrUpdate(configRequestInfo.getSrcIp(), configForm.getSrcUser(), configInfo, time,
configAdvanceInfo, false);
// 发布ConfigDataChangeEvent事件
ConfigChangePublisher.notifyConfigChange(
new ConfigDataChangeEvent(false, configForm.getDataId(), configForm.getGroup(),
configForm.getNamespaceId(), time.getTime()));
...
}
ConfigOperationService的publishConfig方法首先把配置持久化到MySQL,然后发布一个ConfigDataChangeEvent事件,这个ConfigDataChangeEvent事件会异步触发配置文件dump以及通知nacos集群其他节点发生配置变更等操作。
nacos事件监听机制
ConfigChangePublisher#notifyConfigChange()
public static void notifyConfigChange(ConfigDataChangeEvent event) {
...
NotifyCenter.publishEvent(event);
}
ConfigChangePublisher的notifyConfigChange方法调用NotifyCenter的publishEvent方法发布事件。
NotifyCenter#publishEvent(Event)
public static boolean publishEvent(final Event event) {
...
return publishEvent(event.getClass(), event);
...
}
private static boolean publishEvent(final Class<? extends Event> eventType, final Event event) {
...
// 根据事件类型获取对应的事件发布器EventPublisher,
// 获取到的是DefaultPublisher
final String topic = ClassUtils.getCanonicalName(eventType);