这里分析下Nacos Config在Spring Cloud下的使用。整体调用链路如下表所示。
NacosConfigBootstrapConfiguration | |||||
nacosConfigProperties() | |||||
nacosConfigManager() | |||||
nacosPropertySourceLocator() | |||||
NacosPropertySourceLocator#locate() | |||||
loadSharedConfiguration() | |||||
loadExtConfiguration() | |||||
loadApplicationConfiguration() | |||||
NacosConfigAutoConfiguration | |||||
nacosConfigProperties() | |||||
nacosRefreshHistory() | |||||
nacosConfigManager() | |||||
nacosContextRefresher() | |||||
NacosContextRefresher#onApplicationEvent() | |||||
registerNacosListenersForApplications() | |||||
registerNacosListener() |
NacosConfigBootstrapConfiguration
nacosConfigProperties()
加载了spring.cloud.nacos相关配置,生成NacosConfigProperties。
nacosConfigManager()
初始化了NacosConfigManager,主要是根据NacosConfigProperties初始化了ConfigService,这个也是Nacos Client 对外保留的核心对象,用于获取配置,添加监听等。
nacosPropertySourceLocator()
用于初始化了NacosPropertySourceLocator对象,实现了PropertySourceLocator接口,用于加载额外的配置信息。
NacosPropertySourceLocator#locate()
public PropertySource<?> locate(Environment env) {
ConfigService configService = this.nacosConfigProperties.configServiceInstance();
if (null == configService) {
log.warn("no instance of config service found, can't load config from nacos");
return null;
} else {
long timeout = (long)this.nacosConfigProperties.getTimeout();
this.nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService, timeout);
String name = this.nacosConfigProperties.getName();
String dataIdPrefix = this.nacosConfigProperties.getPrefix();
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = name;
}
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = env.getProperty("spring.application.name");
}
CompositePropertySource composite = new CompositePropertySource("NACOS");
this.loadSharedConfiguration(composite);
this.loadExtConfiguration(composite);
this.loadApplicationConfiguration(composite, dataIdPrefix, this.nacosConfigProperties, env);
return composite;
}
}
loadSharedConfiguration()
加载分布式的配置,形如spring.cloud.nacos.config.shared-configs[0]=xxx 的配置。
loadExtConfiguration()
加载扩展配置,如spring.cloud.nacos.config.extension-configs[0]=xxx ,其实我没搞明白这俩有啥区别。
loadApplicationConfiguration()
加载应用主配置信息,这里会加载默认的两个配置,dataIdPrefix+group与dataIdPrefix.fileExtension+group,如果不想加载可以通过配置spring.cloud.nacos.config.group=来避免加载,只加载上面的shared-configs与extension-configs的配置。
NacosConfigAutoConfiguration
nacosConfigProperties()
这里会判断是否有父Context并且包含了NacosConfigProperties,如果有从父Context中直接获取。
nacosRefreshHistory()
初始化了NacosRefreshHistory,用于存储Nacos数据更新历史,最大存储20条。
nacosConfigManager()
初始化了NacosConfigManager,与上面的一致。
nacosContextRefresher()
初始化了NacosContextRefresher,这个是比较核心的类,这个类实现了ApplicationListener,监听ApplicationReadyEvent事件,在Application完成的时候,执行Nacos变化监听。
NacosContextRefresher#onApplicationEvent()
registerNacosListenersForApplications() --> registerNacosListener() --> 这里会新建一个Listener,并通过configService#addListener()方法添加到Nacos的变化监听中。当收到变化的时候,首先添加了刷新纪录nacosRefreshHistory#addRefreshRecord(),其次发布了RefreshEvent事件。
在发布了RefreshEvent事件之后,就可以使用Spring Cloud自带的RefreshScope机制来实现属性的刷新了。在Spring Cloud 监听到变化,会执行ContextRefresher#refresh()。首先会重新加载引导信息,也就会重新调用NacosPropertySourceLocator#locate(),从而从Nacos中读取最新的配置。其次会清空缓存对象,重新以最新的Enviroment生成对象,来达到属性更新的目的。
整体来说Nacos Config在Spring Cloud的实现比较简单。核心使用了Spring Cloud的RefreshScope机制来实现对象属性的动态刷新。
网友评论