上面章节我们讲了服务启动的时候从远程 Nacos 服务端拉到配置,以及服务启动后对需要支持热更新的配置都注册了一个监听器,这个章节我们来说下配置变动后具体是怎么处理的。
回到前面文章说过的 NacosPropertySourceLocator 的 locate()方法看看,该方法首先会通过NacosConfigManager获取一个 ConfigService,我们看下ConfigService是如何创建的:
public ConfigService getConfigService() {
if (Objects.isNull(service)) {
createConfigService(this.nacosConfigProperties);
}
return service;
}
static ConfigService createConfigService(
NacosConfigProperties nacosConfigProperties) {
if (Objects.isNull(service)) {
synchronized (NacosConfigManager.class) {
try {
if (Objects.isNull(service)) {
service = NacosFactory.createConfigService(
nacosConfigProperties.assembleConfigServiceProperties());
}
}
catch (NacosException e) {
log.error(e.getMessage());
throw new NacosConnectionFailureException(
nacosConfigProperties.getServerAddr(), e.getMessage(), e);
}
}
}
return service;
}
// com.alibaba.nacos.api.config.ConfigFactory#createConfigService(java.util.Properties)
public static ConfigService createConfigService(Properties properties) throws NacosException {
try {
Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
Constructor constructor = driverImplClass.getConstructor(Properties.class);
ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);
return vendorImpl;
} catch (Throwable e) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
}
}
从源码可以看到,NacosConfigManager 中会进行一个 ConfigService 单例对象的创建,创建流程最终会委托给 ConfigFactory,使用反射方式创建一个 NacosConfigService 的实例对象,NacosConfigService 是一个很核心的类,配置的获取,监听器的注册都需要经此。
我们看下 NacosConfigService 的构造函数,会去创建一个 ClientWorker 类的对象,这个类是实现配置热更新的核心类。
/**
* 长轮训
*/
private final ClientWorker worker;
public NacosConfigService(Properties properties) throws NacosException {
final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);
ValidatorUtils.checkInitParam(clientProperties);
// 初始化Namespace
initNamespace(clientProperties);
// 创建了一个配置过滤器链,可以采用SPI扩展机制加载对应的过滤器实现类
this.configFilterChainManager = new ConfigFilterChainManager(clientProperties.asProperties());
// 创建了一个服务管理器,内含一个定时轮询线程池,每隔30s拉取一次服务
ServerListManager serverListManager = new ServerListManager(clientProperties);
serverListManager.start();
// 创建了一个客户端工作者,包含了一个代理对象
this.worker = new ClientWorker(this.configFilterChainManager, serverListManager, clientProperties);
// will be deleted in 2.0 later versions
agent = new ServerHttpAgent(serverListManager);
}
再来看下ClientWorker的构造方法:
public ClientWorker(final ConfigFilterChainManager configFilterChainManager, ServerListManager serverListManager,
final NacosClientProperties properties) throws NacosException {
this.configFilterChainManager = configFilte