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中可能变量设置方式可能非常多,导致不能准确定位到变量对应的配置类,所以每次都是刷新所有的配置类和注解类,开销也很大。

相关推荐
墨着染霜华12 小时前
SpringCloud Gateway线上Nginx代理后自定义下划线请求头丢失(app_name/app_version获取不到)完美解决
nginx·spring cloud·gateway
Rain的Java大神之路19 小时前
高并发下的热点账户余额扣减:Redis+Lua脚本实现无锁记账
java·spring boot·redis·后端·spring cloud·缓存·lua
YOU OU1 天前
优雅实现远程调用-OpenFeign
spring cloud
YOU OU1 天前
Spring Cloud概述
后端·spring·spring cloud
随遇而安zx2 天前
SpringCloud---可观测性与监控:Actuator / Micrometer / Prometheus / Grafana 深度解析
spring cloud·grafana·prometheus
LlmCraft|大模型工程实践2 天前
08. Docker Compose 一键编排:多容器应用的指挥家
java·spring cloud·eureka
橘子编程2 天前
Java邮件发送全攻略:从入门到实战
java·开发语言·spring boot·spring·spring cloud·maven
苏渡苇2 天前
HandlerInterceptor 和 WebFilter:两套 HTTP 请求拦截
spring boot·spring·http·spring cloud
随遇而安zx2 天前
SpringCloud---安全(Security / OAuth2 / JWT)设计思想与深度解析
安全·spring cloud
骇客野人2 天前
SpringBoot+SpringCloud高并发系统设计、搭建与落地实施方案
java·spring boot·spring cloud