likes
comments
collection
share

nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决

作者站长头像
站长
· 阅读数 50

前言

本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过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 源码解决无法动态刷新的问题的。

官网步骤:

nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决

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

官网博客:

nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决

debug源码解决问题

debug思路主要是从@NacosValue注解入手,毕竟这个注解上面配置autoRefreshed

确定@NacosValue处理逻辑

关键类NacosValueAnnotationBeanPostProcessor.class、和方法doWithAnnotation nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决 下面方法逻辑就是对@NacosValue注解相关信息的封装然后放到Map里面。这个地方实际是没有去set值或者更新值得,只是在获取@NacosValue注解相关信息,然后封装到一个Map对象(placeholderNacosValueTargetMap)。 nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决

通过打断点看堆栈信息、或者查看方法的引用我们可以发现都是在postProcessBeforeInitialization方法中去调用的,这就是和spring bean的初始化流程接轨了,还记得这个接口吗?

确定placeholderNacosValueTargetMap的使用逻辑

查看map的调用方法NacosValueAnnotationBeanPostProcessor.onApplicationEvent nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决 可以看到属性的刷新也是通过spring的事件发布机制来处理的,接下来就简单了,我们就确认什么时候发布的NacosConfigReceivedEvent

确认事件发布逻辑

通过debug发现没有调用事件发布的方法,这是我们就一层一层往上debug,直到进入下面的方法ClientWorker.executeConfigListen() nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决 因为CachData没有值所以后续的MD5比较以及NacosConfigReceivedEvent事件发布都没有走,这个时候我们就确认CachData应该存什么值,为什么没有值

确认CachData为什么没有值问题

找到set CachData的值代码ClientWorker.addCacheDataIfAbsent()可以看到CacheData主要就是存放的dataidgorup等配置信息

nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决 通过debug发现没有走这个方法,应该是调用这个方法之前逻辑中断了,不断的向上debug,最终找到中断执行的逻辑

nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决

解决NacosPropertySource.autoRefreshed属性为false

因为autoRefreshed赋值的地方有点多,就不一一说明了。我的思路就是因为配置文件是配置了nacos.config.auto-refresh=true我们就看NacosConfigProperties.autoRefresheNacosPropertySource.autoRefreshed是否有关系;

nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决 查看reqNacosConfig()方法被谁调用,loadConfig()在很多地方都有调用,我debug的是下面方法,把nacos.config.bootstrap.log-enable=true配置加上,就会执行loadConfig()方法了 nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决

配置文件增加data-id解决报错,最终缓存能实时刷新

配置文件增加nacos.config.bootstrap.log-enable=true,执行loadConfig()方法报错

nacos无法动态刷新配置前言 本篇文章主要描述在网上没有找到答案时,对框架不熟悉的情况,如何通过debug源码,去解决 最后在配置文件中增加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
评论
请登录