Nacos配置中心
大约 2 分钟源码分析《Nacos》源码分析
配置获取实现
以Spring Cloud应用为例,分析一下应用启动时如何获取Nacos上面的配置。
核心类:NacosPropertySourceLocator
,该类继承了PropertySourceLocator
,PropertySourceLocator
是Spring Cloud提供的接口,该接口的作用是让用户可定制化的将一些配置加载到 Environment。这部分配置获取遵循了 Spring Cloud Config 的理念,即希望能从外部储存获取。
在服务启动准备上下文阶段会调用PropertySourceBootstrapConfiguration#initialize
方法,该方法会根据order排序执行所有PropertySourceLocator
实例的locate
方法。NacosPropertySourceLocator#locate
会获取server端配置,核心代码如下:
@Override
public PropertySource<?> locate(Environment env) {
nacosConfigProperties.setEnvironment(env);
ConfigService configService = nacosConfigManager.getConfigService();
if (null == configService) {
log.warn("no instance of config service found, can't load config from nacos");
return null;
}
long timeout = nacosConfigProperties.getTimeout();
nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService,
timeout);
String name = nacosConfigProperties.getName();
String dataIdPrefix = nacosConfigProperties.getPrefix();
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = name;
}
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = env.getProperty("spring.application.name");
}
//获取配置返回,后面加载到Environment中
CompositePropertySource composite = new CompositePropertySource(
NACOS_PROPERTY_SOURCE_NAME);
// 加载共享配置
loadSharedConfiguration(composite);
//加载扩展配置
loadExtConfiguration(composite);
//加载应用配置
loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
return composite;
}
调用链如下:
上述加载配置会调用com.alibaba.nacos.api.config.ConfigService#getConfig
方法去获取配置,核心逻辑在com.alibaba.nacos.client.config.NacosConfigService#getConfigInner
方法中,
private String getConfigInner(String tenant, String dataId, String group, long timeoutMs) throws NacosException {
group = null2defaultGroup(group);
ParamUtils.checkKeyParam(dataId, group);
ConfigResponse cr = new ConfigResponse();
cr.setDataId(dataId);
cr.setTenant(tenant);
cr.setGroup(group);
// 优先使用本地配置,我本地配置文件在C:\Users\Administrator\nacos\config\fixed-nacos.cmp_8848-dev_nacos\snapshot-tenant目录
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
if (content != null) {
LOGGER.warn("[{}] [get-config] get failover ok, dataId={}, group={}, tenant={}, config={}", agent.getName(),
dataId, group, tenant, ContentUtils.truncateContent(content));
cr.setContent(content);
configFilterChainManager.doFilter(null, cr);
content = cr.getContent();
return content;
}
// 如果本地不存在配置文件,从服务端获取配置文件
try {
String[] ct = worker.getServerConfig(dataId, group, tenant, timeoutMs);
cr.setContent(ct[0]);
configFilterChainManager.doFilter(null, cr);
content = cr.getContent();
return content;
} catch (NacosException ioe) {
if (NacosException.NO_RIGHT == ioe.getErrCode()) {
throw ioe;
}
LOGGER.warn("[{}] [get-config] get from server error, dataId={}, group={}, tenant={}, msg={}",
agent.getName(), dataId, group, tenant, ioe.toString());
}
LOGGER.warn("[{}] [get-config] get snapshot ok, dataId={}, group={}, tenant={}, config={}", agent.getName(),
dataId, group, tenant, ContentUtils.truncateContent(content));
content = LocalConfigInfoProcessor.getSnapshot(agent.getName(), dataId, group, tenant);
cr.setContent(content);
configFilterChainManager.doFilter(null, cr);
content = cr.getContent();
return content;
}
配置刷新实现
配置刷新是通过事件监听实现的,com.alibaba.cloud.nacos.refresh.NacosContextRefresher监听了ApplicationReadyEvent事件,ApplicationReadyEvent在服务准备好提供请求后发布。