nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决
前言
本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决问题。所以这篇文章记录了自己解决问题的思路、以及debug流程。
问题描述
按照网上的配置都改好了,也去官网找了资料,还是没法动态刷新。只有重启的时候会重新拉取配置。
-
环境: springboot2.4.5、 nacos服务器版本2.4.1、nacos 客户端依赖0.2.11
-
配置:
nacos.config.server-addr=http://xxxx.xx.xx:8848 nacos.config.namespace=bec4dc34-7d71-4c6b-a24d-4ac2e429b7be nacos.config.username=nacos nacos.config.password=nacos # 开启自动刷新 nacos.config.auto-refresh=true nacos.config.enable-remote-sync-config=true nacos.config.config-long-poll-timeout=46000 -
代码:
@RestController @RequestMapping("properties") public class ReadNacosProperties { @NacosValue(value = "${me.user:test}", autoRefreshed = true) private String meUser; @GetMapping("/q") public Object test(){ return meUser; } }@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) @NacosPropertySource(dataId = "jeecgBoot") public class NacosApplication { public static void main(String[] args) { SpringApplication.run(NacosApplication.class, args); } }
我这代码和配置没啥问题吧,能正常拉取配置,就是改了远程配置,访问接口还是拿到的是历史配置。
解决方案
先把我的解决方案说了吧,解决思路下面再慢慢分析。 配置文件增加以下两个配置:
nacos.config.data-id=jeecgBoot
nacos.config.bootstrap.log-enable=true
当然还有其他的配置方式,下面的debug流程主要就是解释为什么要配置这两个属性
排查思路
先去官网和百度看看了,都没有解决我的问题,只有自己跟一下源码了。 下面看看官网的使用教程,以及官方博客给出的一些解决思路,最后就是看我如何通过debug 源码解决无法动态刷新的问题的。
官网步骤:

实际按照官网这种写法是没有问题的,能自动刷新。我当时启动类上面只配置了
dataId,autoRefreshed我是配置在配置文件,如果我当时注意到了就会不会有这篇文章了。(ps:想知道为什么就往下面看吧)
官网博客:

debug源码解决问题
debug思路主要是从@NacosValue注解入手,毕竟这个注解上面配置autoRefreshed。
确定@NacosValue处理逻辑
关键类NacosValueAnnotationBeanPostProcessor.class、和方法doWithAnnotation
下面方法逻辑就是对@NacosValue注解相关信息的封装然后放到Map里面。这个地方实际是没有去set值或者更新值得,只是在获取@NacosValue注解相关信息,然后封装到一个Map对象(placeholderNacosValueTargetMap)。

通过打断点看堆栈信息、或者查看方法的引用我们可以发现都是在
postProcessBeforeInitialization方法中去调用的,这就是和springbean的初始化流程接轨了,还记得这个接口吗?
确定placeholderNacosValueTargetMap的使用逻辑
查看map的调用方法NacosValueAnnotationBeanPostProcessor.onApplicationEvent
可以看到属性的刷新也是通过spring的事件发布机制来处理的,接下来就简单了,我们就确认什么时候发布的NacosConfigReceivedEvent
确认事件发布逻辑
通过debug发现没有调用事件发布的方法,这是我们就一层一层往上debug,直到进入下面的方法ClientWorker.executeConfigListen()
因为CachData没有值所以后续的MD5比较以及NacosConfigReceivedEvent事件发布都没有走,这个时候我们就确认CachData应该存什么值,为什么没有值
确认CachData为什么没有值问题
找到set CachData的值代码ClientWorker.addCacheDataIfAbsent()可以看到CacheData主要就是存放的dataid、gorup等配置信息
通过debug发现没有走这个方法,应该是调用这个方法之前逻辑中断了,不断的向上debug,最终找到中断执行的逻辑

解决NacosPropertySource.autoRefreshed属性为false
因为autoRefreshed赋值的地方有点多,就不一一说明了。我的思路就是因为配置文件是配置了nacos.config.auto-refresh=true我们就看NacosConfigProperties.autoRefreshe 和NacosPropertySource.autoRefreshed是否有关系;
查看reqNacosConfig()方法被谁调用,loadConfig()在很多地方都有调用,我debug的是下面方法,把nacos.config.bootstrap.log-enable=true配置加上,就会执行loadConfig()方法了

配置文件增加data-id解决报错,最终缓存能实时刷新
配置文件增加nacos.config.bootstrap.log-enable=true,执行loadConfig()方法报错
最后在配置文件中增加data-id 配置解决报错,实现动态刷新
总结
主要问题就是在初始化时候NacosPropertySource.autoRefreshed属性出了问题;
有以下几种处理方式
nacos.config.data-id=jeecgBoot
nacos.config.bootstrap.enable=true
或者
nacos.config.data-id=jeecgBoot
nacos.config.bootstrap.log-enable=true
还有就是官网说的在启动类上增加一下标识并且设置autoRefeshed
@NacosPropertySource(dataId = "jeecgBoot",autoRefreshed = true)
选其中一种即可,就不要像我一样,启动类上配置dataId,配置文件设置autoRefreshed
ps 这篇文章主要是
debug流程,后面再梳理一篇nacos核心执行流程文章
转载自:https://juejin.cn/post/7426282721545699337