【Spring Cloud Alibaba系列】Nacos 长轮询机制

761 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

配置加载执行路径:loadApplicationConfiguration->loadNacosDataIfPresent->loadNacosPropertySource->build->loadNacosData

可以发现基于configService.getConfig从Nacos配置中心上加载配置返回,事件订阅机制在哪里实现?可查看NacosContextRefresher类,它实现一个ApplicationReadyEvent事件监听,这就是在上下文准备好后触发这个事件。

public class NacosContextRefresher implements ApplicationListener<ApplicationReadyEvent>,ApplicationContextAware{
	@Override
	public void onApplicationEvent(ApplicationReadyEvent event){
	if(this.ready.compareAndSet(false,true)){
	this.registerNacosListenerForApplications();
	}
	}
}

当监听时间到后,会调用registerNacosListenerForApplications方法实现Nacos事件监听的注册

private void registerNacosListener(final String group,final String dataId){
Listener listener = listenerMap.computeIfAbsent(dataId,i->new listener(){
	@Override
	public void receiveConfigInfo(String configInfo){
	refreshHistory.add(dataId,md5);
	applicationContext.publishEvent(new RefreshEvent(this,null,"Refresh Nacos Config"));
	if(log.isDebugEnabled()){
	log.debug("Refresh Nacos config group"+group+",dataId"+dataId);
	}
	}
});
}

看出当收到配置修改的回调时,通过applicationContext.publishEvent发布一个RefreshEvent事件,这个事件的监听实现在RefreshEventListener类。

public class RefreshEventListener implements SmartApplicationLIstener{
	if(this.ready.get()){
	log.debug("Event received"+event.getEventDesc());
	Set<String> keys=this.refresh.refresh();
	log.info("Refresh keys changed:"+keys);
	}
}

在handle方法中调用refresh.refresh()方法完成配置的更新。

接着关注客户端和服务端之间的长轮询机制,以及服务端实时推送配置更新信息给客户端。

NacosFactory.createConfigService

客户端的长轮询定时任务是在NacosFactory.createConfigService构建ConfigService对象实例启动

  • 通过Class.forName来加载NacosConfigService类
  • 使用反射完成NacosConfigService类的实例化
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 configService = constructor.newInstance(properties);
	return configService;
	}catch(Throwable e){
	throw new NacosExcepion(NacosException.CLIENT_INVALID_PARAM,e);
	}
}