Nacos动态更新配置,修改后为什么不生效?

5,243 阅读2分钟

问题描述: 最近在搭建Spring Cloud Alibaba 这一套架构。在阅读了些许博客后,开始操作。

  • 我在start.aliyun.com上用阿里云的脚手架生成的nacos的应用,勾选了服务注册发现和动态配置两个依赖。
  • 生成git代码后,clone到本地,删除了一些不必要的模块demo代码后。修改配置连接到我搭建的nacos,nacos采用的是单机启动,没有配置数据库或者Redis缓存等,重启就会丢失所有配置文件的那种。
  • 修改完应用的相关配置后,启动并能成功注册到我搭建的nacos并能成功读取配置初始化我相关配置参数。

问题:启动成功后当我修改对应dataId的配置文件时,我能清楚的感知到修改后的配置并没有成功应用到我的应用里。

尝试过解决问题的方法:

  • 代码debug,我能看到在跟读代码的时候,应用是获取到了最新的配置信息,但是在我实现的 InitializingBean 接口中,参数会被原来的值覆盖。

截图: 应用成功启动: image.png

nacos配置:

image.png

nacos配置修改后:更改了user.name 和user.age两个参数

image.png

应用日志输出:

image.png

@Configuration
@EnableConfigurationProperties(User.class)
public class NacosConfigDemoConfiguration {

    @Autowired
    private NacosConfigManager nacosConfigManager;

    @Autowired
    private User user;

    @Value("${user.name}")
    private String userName;

    @Value("${user.age}")
    private int userAge;

    @Bean
    public ApplicationRunner runner() {
        return args -> {
            String dataId = "SpringCloudDemo.properties";
            String group = "DEFAULT_GROUP";
            nacosConfigManager.getConfigService().addListener(dataId, group, new AbstractListener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    System.out.println("[Listener] " + configInfo);
                    System.out.println("[Before User] " + user);

                    Properties properties = new Properties();
                    try {
                        properties.load(new StringReader(configInfo));
                        String name = properties.getProperty("user.name");
                        int age = Integer.valueOf(properties.getProperty("user.age"));
                        user.setName(name);
                        user.setAge(age);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    System.out.println("[After User] " + user);
                }
            });
        };
    }


    @PostConstruct
    public void init() {
        System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
    }

    @PreDestroy
    public void destroy() {
        System.out.printf("[destroy] user name : %s , age : %d%n", userName, userAge);
    }
}

日志第一块部分 Listener 是这里的代码获取输出的

user配置类代码:

@RefreshScope
@ConfigurationProperties(prefix = "user")
public class User implements InitializingBean, DisposableBean {

    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("[afterPropertiesSet()] " + toString());
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("[destroy()] " + toString());
    }
}

可以从日志中发现,配置其实是有通知到本地应用的,但是在user中,InitializingBean 这个接口重新生成的user相关的参数却是修改前的。

说明:NacosConfigDemoConfiguration#中的ApplicationRunner 这个bean之前没有启用,在user的afterPropertiesSet()和destroy()方法中无法明显的观测到动态配置未刷新的原因。在启用后会发现,其实修改后的配置是通知到了应用的,但是搞不懂为什么新的值会被原有的值覆盖。

排查后发现可能是版本问题,但是我用的阿里云原生的脚手架生成的,按理说不会出现cloud和boot的版本冲突。spring-boot-starter-parent切换了几个版本后排查后均会出现此问题: 这里贴一下使用的版本:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.3</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  <version>2021.0.4.0</version>
</dependency>
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  <version>2021.0.4.0</version>
</dependency>

希望大佬能帮我解决一下问题。谢谢~