Apollo/Nacos配置动态刷新原理及优劣

本文对比分析了Apollo和Nacos的配置动态刷新机制。Apollo提供自定义监听器,但需自行实现动态刷新;Nacos提供默认实现,但可能导致全bean刷新。Nacos2022.0.0.0-RC1版本后可选择刷新模式。在配置更新时,建议考虑特定bean刷新,避免不必要的组件重注册问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 配置方式

这里只说与Spring集成后的配置方式,这也是项目中主要使用的方式

Apollo

  1. 在属性上直接加@value注解,这个属性就会随着配置的更改动态更新
  2. 类实现ConfigChangeListener,在类中方法上@ApolloConfigChangeListener注解,注解在方法上,监控配置的变化,配置变化后会自定义方法来达到动态刷新bean的目的

Nacos

  1. Nacos无需任何配置,即可对有@ConfigurationProperties注解的类进行配置的动态刷新
  2. Nacos自2022.0.0.0-RC1版本后可通过spring.cloud.nacos.config.refresh-bahavior指定刷新模式,默认是all_beans(刷新所有bean),可选specific_bean (只刷新有配置值更改的bean)

优劣对比

先说结论,二者的优劣势对比,具体的原理机制等相对复杂,放后文详细讲解

Apollo

优势

  • 提供出listener,使用者可灵活自行定制bean的刷新方式

劣势

  • Apollo除@Value注解外不提供动态刷新的默认实现方案,而@Value注解平常用的较少,就比较鸡肋,用户想要用@ConfigurationProperties配置类的方式动态刷新,必须要自己去实现

Nacos

优势

  • 有动态刷新的默认实现,用户可直接使用,且从2022.0.0.0-RC1版本后可自选bean的刷新模式

劣势

  • 不管选用哪种nacos的刷新方案,RefreshScope域都会全刷新,触发RefreshScopeRefreshedEvent事件的发布,如eureka会订阅该事件,并于该事件发布时,触发eurekaClient的重新注册,若是配置热更新的比较频繁,那么会触发eurekaClient的频繁重注册

最终抉择

  • 动态热更新的时候,肯定是更新哪个配置,那么只将与这个配置对应的bean进行更新最好,若是用的nacos,那么可选用2022.0.0.0-RC1版本,bean的刷新行为选用specific_bean指定刷新,若是用的Apollo,需自己实现,也可参考nacos中的SmartConfigurationPropertiesRebinder类,进行自实现,配置动态刷新后,建议还是要发布下RefreshScopeRefreshedEvent事件,使得依赖该事件发布的其他组件,在配置刷新后,可重新配置与该之相关的的内容,避免真的更改了例如eureka的配置后,eureka因不能重注册client导致的配置无法生效的问题。这里比较坑的地方就是springcloud没有提供一种机制,可监听自己的配置更改及事件发布对应着触发事件,进行导致只是更改了用户自定义的一些配置也触发了eureka客户端重注册这种看似风马牛不相及的行为出现

动态刷新机制

这里只以nacos为例,重点讲解服务通过监听器拿到配置变更之后的流程,Apollo在自行实现时,也可参考此流程

  1. NacosContextRefresher监听ApplicationReadyEvent事件,会在应用准备启动时间发布后,注册NacosListener
  2. 在注册时,会实现listener的innerReceive方法,在配置变更后,会通知到该方法,该方法会触发事件的发布: applicationContext.publishEvent(new RefreshEvent(this, null, "Refresh Nacos config"));
	@Override
	public void onApplicationEvent(ApplicationReadyEvent event) {
   
   
		// many Spring context
		if (this.ready.compareAndSet(false, true)) {
   
   
			this.registerNacosListenersForApplications();
		}
	}
	/**
	 * register Nacos Listeners.
	 */
	private void registerNacosListenersForApplications() {
   
   
		if (isRefreshEnabled()) {
   
   
			for (NacosPropertySource propertySource : NacosPropertySourceRepository
					.getAll()) {
   
   
				if (!propertySource.isRefreshable()) {
   
   
					continue;
				}
				String dataId = propertySource.getDataId();
				registerNacosListener(propertySource.getGroup(), dataId);
			}
		}
	}
	
	private void registerNacosListener(final String groupKey, final String dataKey) {
   
   
		String key = NacosPropertySourceRepository.getMapKey(dataKey, groupKey);
		Listener listener = listenerMap.computeIfAbsent(key,
				lst -> new AbstractSharedListener() {
   
   
					@Override
					public void innerReceive(String dataId, String group,
							String configInfo) {
   
   
						refreshCountIncrement();
						nacosRefreshHistory.addRefreshRecord(dataId, group, configInfo);
						// 这里发布RefreshEvent事件,用以刷新bean实例
						applicationContext.publishEvent(
								new RefreshEvent(this, null, "Refresh Nacos config"));
						if (log.isDebugE
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值