Nacos如何通过RefreshScope实现配置自动更新

本文主要是了解Nacos中配置更新后,如何实现配置项自动更新。

实现方式

有两种方式,使用@ConfigurationProperties注解调用get请求或者@RefreshScope + @Value这两种来实现配置的刷新。

配置属性

现象

初始值是false,修改Nacos中的配置文件为true。很快配置项就变了。

idea日志

可以看到是触发了配置的更新并打印了配置变化项。

DEBUG

通过Debug知道大体流程如下:

配置更新的大体流程如上。NacosClient中使用了一个线程池的无线循环来监测配置的变更,即长轮询的方式去Nacos Server中去获取配置变更。

自动刷新

从上面我们可以得到配置已经更新到了Environment中,但是持有配置项的类由于已经初始化是不会变更已经设置进去的属性。容器工厂通过销毁bean,重建bean的方式来重新初始化配置对象,达到整个配置更新的操作。

配置刷新(@ConfigurationProperties)

refreshEnvironment(刷新环境变量)

刷新环境变量同时通过对比找出变更的配置项,再触发环境改变Event事件。

ConfigurationPropertiesRebinder(配置重新绑定)

配置重新绑定类同步也实现ApplicationListener接口,监听了EnvironmentChangeEvent的改变。是通过beanFactory来销毁bean和初始化bean。

疑问?

由于Spring框架的限制,当刷新配置项时,所有的配置项都会刷新,走bean的销毁和创建过程。往往我们只需要更新其中变化的配置项即可。

已经得到了变更的配置项了,结果还是刷新了所有的配置项。如果不需要进行刷新,也可以添加自定义的配置项,把对应的配置加进来即可。

默认是hikari数据库连接池的datasource对象。防止刷新时造成数据库连接池重新销毁创建,造成连接的浪费。


其实我们可以通过keys想办法定位对应的配置项,在Environment中附加每一个属性对应的来源。这样可以直接通过变量操作来源进行对应的配置刷新。如果想粒度更小的话,在初始化过程中反射设置属性时,可以只设置变更的属性,最小的代价变更配置类的变量值。

单例,通过反射的方式设置配置变更项。可以通过get方式来获取变量后的值。

变量刷新(@RefreshScope + @Value)

非配置类上配置了@RefreshScope注解后,在abstractApplicationContext中实例化bean时没有走单例或者原型的初始化方式。是通过Scope的方式自定义bean的获取方式。

Scope内部会维护一个数组缓存刷新对象。每次获取时从缓存内部获取对象,如果不存在则重新创建,就会重新走一遍对象的实例化,因此Value对象就会重新被赋值。

缓存清除

依据配置,同理可以知道也是通过event机制获取到配置更新,进而去清除缓存。我们debug一下调用栈看一下。

最后其实就是调用了cache的clear方法,清除了所有缓存。再次获取bean时,缓存中不存在,就会重新进行创建。

疑问?

这里也是清除所有缓存,所有@RefreshScope类都会重新创建。虽然对应的配置也会更新,但是也会触发postConstruct,destory等方法,导致出现一些无法预料的问题。应用自动刷新同时也要考虑上述的情况,尽量进行规避。

总结

个人建议走配置更新的方式。通过每次使用get方法来获取到最新的变量即可。配置类没有被重新创建,开销更小,框架也是自动已经集成好了。SpringBoot中可能变量设置方式可能非常多,导致不能准确定位到变量对应的配置类,所以每次都是刷新所有的配置类和注解类,开销也很大。

相关推荐
AAA修煤气灶刘哥1 小时前
缓存这「加速神器」从入门到填坑,看完再也不被产品怼慢
java·redis·spring cloud
AAA修煤气灶刘哥1 小时前
接口又被冲崩了?Sentinel 这 4 种限流算法,帮你守住后端『流量安全阀』
后端·算法·spring cloud
T_Ghost5 小时前
SpringCloud微服务服务容错机制Sentinel熔断器
spring cloud·微服务·sentinel
喂完待续7 小时前
【序列晋升】28 云原生时代的消息驱动架构 Spring Cloud Stream的未来可能性
spring cloud·微服务·云原生·重构·架构·big data·序列晋升
惜.己21 小时前
Docker启动失败 Failed to start Docker Application Container Engine.
spring cloud·docker·eureka
chenrui3101 天前
Spring Boot 和 Spring Cloud: 区别与联系
spring boot·后端·spring cloud
喂完待续2 天前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
麦兜*2 天前
MongoDB 性能调优:十大实战经验总结 详细介绍
数据库·spring boot·mongodb·spring cloud·缓存·硬件架构
小马爱打代码4 天前
Spring Cloud LoadBalancer 核心原理
spring cloud