alibaba / nacos

an easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.
https://nacos.io
Apache License 2.0
30.33k stars 12.85k forks source link

在配置中心删除某项配置之后无法将这项配置更新为空值 #12690

Closed spice-wolf closed 1 month ago

spice-wolf commented 1 month ago

Describe the bug 例如,在配置中心上有一项配置:

test-config: 测试配置1

如果把这项配置完全删除掉,程序中读取到的testConfig值还是测试配置1,但是期望的testConfig值应该是null

从程序的日志中可以看到nacos-client拿到了变动后的配置,并且准确地报告了是test-config这个配置项有变更。我大概了解配置动态刷新的原理:拿到变更后的配置,将其中的配置项与程序当前的配置项相比较,如果不相等则刷新对应的配置项的值。是否是因为变更后的配置中test-config这个配置项被删除掉了,导致无法和程序的值进行比较,所以没有更新程序中的值呢?

我觉得删除配置项这个动作,在大部分情况下是期望将这个配置项更新为null或者使用默认值(如果有默认值的话),所以我觉得当前的处理不太符合使用者的直觉,很大可能会造成隐患。

我在这个仓库的issues中找到了一个类似的问题:#11170 ,但它目前是closed状态。我现在还无法确定这是nacos的问题,还是spring cloud的问题(因为我当前使用的依赖是spring-cloud-starter-alibaba-nacos-config),所以我提了这个issue来寻找一下答案以及后续的处理。期待回复~

Expected behavior 删除掉配置中心上的配置项之后,程序中的对应配置项应该刷新为null或者默认值,或者其他更好的处理

Actually behavior 实际上,目前删除掉配置中心上的配置项之后,程序中的对应配置项没有任何变化,还保留着最后一次生效的值

How to Reproduce 使用spring-cloud-starter-alibaba-nacos-config:2023.0.1.0按照上述描述去操作即可复现

Desktop (please complete the following information):

Additional context nothing

XiaZhouxx commented 1 month ago

我测试是生效了的, 你配置类有使用@RefreshScope注解吗?

spice-wolf commented 1 month ago

我测试是生效了的, 你配置类有使用@RefreshScope注解吗?

好吧,是我不严谨了。我测试了在配置类上使用以及不使用@RefreshScope注解这两种情况:

  1. 在配置类上使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,也正常动态刷新为null。这是符合期望的行为
  2. 在配置类上不使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,没有正常动态刷新为null,而是继续保持了最后一次生效的值。这是不符合期望的行为

根据测试结果来看,似乎并不是nacos的问题🤐?

XiaZhouxx commented 1 month ago

我测试是生效了的, 你配置类有使用@RefreshScope注解吗?

好吧,是我不严谨了。我测试了在配置类上使用以及不使用@RefreshScope注解这两种情况:

  1. 在配置类上使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,也正常动态刷新为null。这是符合期望的行为
  2. 在配置类上不使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,没有正常动态刷新为null,而是继续保持了最后一次生效的值。这是不符合期望的行为

根据测试结果来看,似乎并不是nacos的问题🤐?

那就奇怪了 使用spring-cloud-starter-alibaba-nacos-config按道理没加@RefreshScope是动态刷新不了的

spice-wolf commented 1 month ago

我测试是生效了的, 你配置类有使用@RefreshScope注解吗?

好吧,是我不严谨了。我测试了在配置类上使用以及不使用@RefreshScope注解这两种情况:

  1. 在配置类上使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,也正常动态刷新为null。这是符合期望的行为
  2. 在配置类上不使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,没有正常动态刷新为null,而是继续保持了最后一次生效的值。这是不符合期望的行为

根据测试结果来看,似乎并不是nacos的问题🤐?

那就奇怪了 使用spring-cloud-starter-alibaba-nacos-config按道理没加@RefreshScope是动态刷新不了的

spring-cloud-starter-alibaba-nacos-config做了增强呀,如果你在配置类上加了@ConfigurationProperties注解(一般来说,配置类都会加上这个注解),但是没加@RefreshScope也是可以正常动态刷新的。只是在删除配置时没法正常刷新成null值,这一点我感觉很奇怪。如果加上@RefreshScope注解时支持这样的操作,那么没加@RefreshScope注解时是不是也应该支持这样的操作才对?这样逻辑才是统一的

misakacoder commented 1 month ago

我测试是生效了的, 你配置类有使用@RefreshScope注解吗?

好吧,是我不严谨了。我测试了在配置类上使用以及不使用@RefreshScope注解这两种情况:

  1. 在配置类上使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,也正常动态刷新为null。这是符合期望的行为
  2. 在配置类上不使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,没有正常动态刷新为null,而是继续保持了最后一次生效的值。这是不符合期望的行为

根据测试结果来看,似乎并不是nacos的问题🤐?

那就奇怪了 使用spring-cloud-starter-alibaba-nacos-config按道理没加@RefreshScope是动态刷新不了的

使用spring-cloud-starter-alibaba-nacos-config但是没加@RefreshScope是可以正常动态刷新的,只是在删除配置时没法正常刷新成null值,这一点我也感觉很奇怪。如果加上@RefreshScope注解时支持这样的操作,那么没加@RefreshScope注解时是不是也应该支持这样的操作才对?这样逻辑才是统一的

不加@RefreshScope刷新不了哦,我这边刚好有个demo测试了一下,nacos是2.4.2,spring-cloud-starter-alibaba-nacos-config是2023.0.1.2

XiaZhouxx commented 1 month ago

我测试是生效了的, 你配置类有使用@RefreshScope注解吗?

好吧,是我不严谨了。我测试了在配置类上使用以及不使用@RefreshScope注解这两种情况:

  1. 在配置类上使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,也正常动态刷新为null。这是符合期望的行为
  2. 在配置类上不使用@RefreshScope注解时:修改配置中心上的配置项,正常动态刷新为修改后的值;将配置中心上的配置项删除,没有正常动态刷新为null,而是继续保持了最后一次生效的值。这是不符合期望的行为

根据测试结果来看,似乎并不是nacos的问题🤐?

那就奇怪了 使用spring-cloud-starter-alibaba-nacos-config按道理没加@RefreshScope是动态刷新不了的

使用spring-cloud-starter-alibaba-nacos-config但是没加@RefreshScope是可以正常动态刷新的,只是在删除配置时没法正常刷新成null值,这一点我也感觉很奇怪。如果加上@RefreshScope注解时支持这样的操作,那么没加@RefreshScope注解时是不是也应该支持这样的操作才对?这样逻辑才是统一的

但是实际上的实现逻辑也是需要加上注解才能动态刷新, 官方文档也提到了我本地测试也是这样, 我奇怪的是居然没加可以实现动态刷新.

spice-wolf commented 1 month ago

不加@RefreshScope刷新不了哦,我这边刚好有个demo测试了一下,nacos是2.4.2,spring-cloud-starter-alibaba-nacos-config是2023.0.1.2

spring-cloud-starter-alibaba-nacos-config做了增强呀,如果你在配置类上加了@ConfigurationProperties注解也是支持动态刷新的

spice-wolf commented 1 month ago

但是实际上的实现逻辑也是需要加上注解才能动态刷新, 官方文档也提到了我本地测试也是这样, 我奇怪的是居然没加可以实现动态刷新.

spring-cloud-starter-alibaba-nacos-config做了增强呀,如果你在配置类上加了@ConfigurationProperties注解也是支持动态刷新的

spice-wolf commented 1 month ago

我们先对齐一下我们的问题复现demo吧😂 下面是我用来复现问题的demo:

  1. 配置类TestConfig

    @Data
    @Configuration
    @ConfigurationProperties(prefix = "test")
    public class TestConfig {
    
    private String config;
    }
  2. 一个打印配置的程序:

    @Component
    @RequiredArgsConstructor
    public class TestConfigPrinter implements CommandLineRunner {
    
    private final TestConfig testConfig;
    
    @Override
    public void run(String... args) throws Exception {
        new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                System.out.println("测试配置:" + testConfig.getConfig());
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }
    }

可以依次:test.config配置项的值改成配置1、将test.config配置项的值改成配置2、将test.config配置项删除掉 来观察控制台输出从而复现问题

XiaZhouxx commented 1 month ago

我们先对齐一下我们的问题复现demo吧😂 下面是我用来复现问题的demo:

  1. 配置类TestConfig
@Data
@Configuration
@ConfigurationProperties(prefix = "test")
public class TestConfig {

    private String config;
}
  1. 一个打印配置的程序:
@Component
@RequiredArgsConstructor
public class TestConfigPrinter implements CommandLineRunner {

    private final TestConfig testConfig;

    @Override
    public void run(String... args) throws Exception {
        new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                System.out.println("测试配置:" + testConfig.getConfig());
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }
}

可以依次:test.config配置项的值改成配置1、将test.config配置项的值改成配置2、将test.config配置项删除掉 来观察控制台输出从而复现问题

是的 我看了一下确实, 我测试用的@Value

XiaZhouxx commented 1 month ago

看了一下大概逻辑是spring-cloud提供的ConfigurationPropertiesRebinder 我大概看了一下逻辑应该就是从项目配置中找到对应的配置绑定set值进去, 如果没有找到对应配置就不设置值,此时就保留了上一次的值

XiaZhouxx commented 1 month ago

@RefreshScope标识的类如果刷新会重新创建一个配置bean, 没有找到配置的情况就是默认配置值/空值

spice-wolf commented 1 month ago

是的👍所以这个问题该不该修复呢?我感觉还是把值设置为null会合理一些,和@RefreshScope的逻辑保持一致

XiaZhouxx commented 1 month ago

是的👍所以这个问题该不该修复呢?我感觉还是把值设置为null会合理一些,和@RefreshScope的逻辑保持一致

这个不是问题吧, 首先这两个注解是spring-cloud提供的实现,看可以去spring-cloud-alibaba社区提个issue, 然后这里官方文档也明确说明使用@RefreshScope来实现配置动态更新 https://nacos.io/docs/latest/ecology/use-nacos-with-spring-cloud/#%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86

spice-wolf commented 1 month ago

是的👍所以这个问题该不该修复呢?我感觉还是把值设置为null会合理一些,和@RefreshScope的逻辑保持一致

这个不是问题吧, 首先这两个注解是spring-cloud提供的实现,看可以去spring-cloud-alibaba社区提个issue, 然后这里官方文档也明确说明使用@RefreshScope来实现配置动态更新 https://nacos.io/docs/latest/ecology/use-nacos-with-spring-cloud/#%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86

我会觉得这是个问题,要么不加@RefreshScope注解时就不要支持动态刷新,要么就和加上@RefreshScope注解时的动态刷新逻辑保持一致。但确实,这不是Nacos的问题。我会去spring-cloud-alibaba社区看看,如果还没有人提问过这个问题,我会提个issue 感谢你的解答😀

XiaZhouxx commented 1 month ago

是的👍所以这个问题该不该修复呢?我感觉还是把值设置为null会合理一些,和@RefreshScope的逻辑保持一致

这个不是问题吧, 首先这两个注解是spring-cloud提供的实现,看可以去spring-cloud-alibaba社区提个issue, 然后这里官方文档也明确说明使用@RefreshScope来实现配置动态更新 https://nacos.io/docs/latest/ecology/use-nacos-with-spring-cloud/#%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86

我会觉得这是个问题,要么不加@RefreshScope注解时就不要支持动态刷新,要么就和加上@RefreshScope注解时的动态刷新逻辑保持一致。但确实,这不是Nacos的问题。我会去spring-cloud-alibaba社区看看,如果还没有人提问过这个问题,我会提个issue 感谢你的解答😀

看了一下应该是spring-cloud社区在考虑增强 https://github.com/spring-cloud/spring-cloud-commons/issues/1372

spice-wolf commented 1 month ago

是的👍所以这个问题该不该修复呢?我感觉还是把值设置为null会合理一些,和@RefreshScope的逻辑保持一致

这个不是问题吧, 首先这两个注解是spring-cloud提供的实现,看可以去spring-cloud-alibaba社区提个issue, 然后这里官方文档也明确说明使用@RefreshScope来实现配置动态更新 https://nacos.io/docs/latest/ecology/use-nacos-with-spring-cloud/#%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86

我会觉得这是个问题,要么不加@RefreshScope注解时就不要支持动态刷新,要么就和加上@RefreshScope注解时的动态刷新逻辑保持一致。但确实,这不是Nacos的问题。我会去spring-cloud-alibaba社区看看,如果还没有人提问过这个问题,我会提个issue 感谢你的解答😀

看了一下应该是spring-cloud社区在考虑增强 spring-cloud/spring-cloud-commons#1372

好的,非常感谢👍