Azure Spring Cloud AppConfiguration 刷新不起作用

Azure Spring Cloud AppConfiguration refresh is not working

我在使用

刷新任何东西时遇到了一些问题,无论是@ConfigurationProperties 还是@Value
implementation("com.azure.spring:azure-spring-cloud-appconfiguration-config:2.1.1")

图书馆。从我可以找到和调试的内容来看,调用了内部 AppConfigurationRefresh class 并创建了 RefreshEvent 以正确响应 Azure Config Server 中所做的更改。问题是,当更新上下文时,也应该有新的值被 ContextRefresher 识别,这对我来说不是这种情况。

Spring 启动 ContextRefresher

    public synchronized Set<String> refreshEnvironment() {
        Map<String, Object> before = extract(this.context.getEnvironment().getPropertySources());
        updateEnvironment();
        Set<String> keys = changes(before, extract(this.context.getEnvironment().getPropertySources())).keySet();
        this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));
        return keys;
    }

该刷新方法的结果始终为空,这意味着未发现任何更改。

刷新事件生成的日志:

2021-11-29 19:53:03.543  INFO [] 34820 --- [         task-2] c.a.s.c.config.AppConfigurationRefresh   : Configuration Refresh Event triggered by /myprefix/my.config.value
2021-11-29 19:53:53.694  INFO [] 34820 --- [         task-2] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-/application/https://my-config-store-stage.azconfig.io/dev'}]
2021-11-29 19:53:53.719  INFO [] 34820 --- [         task-2] o.s.boot.SpringApplication               : The following profiles are active: messaging,db,dev
2021-11-29 19:53:53.736  INFO [] 34820 --- [         task-2] o.s.boot.SpringApplication               : Started application in 3.347 seconds (JVM running for 158.594)
2021-11-29 19:54:01.265  INFO [] 34820 --- [         task-2] o.s.c.e.event.RefreshEventListener       : Refresh keys changed: []
2021-11-29 19:54:03.553  INFO [] 34820 --- [   scheduling-1] d.l.d.a.s.c.AppConfigurationUpdater      : All configurations were refreshed.

bootstrap.yml

spring:
      cloud:
        azure:
          appconfiguration:
            stores:
              - connection-string: ${connection-string}
                selects:
                  - key-filter: '/myprefix/'
                    label-filter: dev
    
                monitoring:
                  enabled: true
                  refresh-interval: 1s
                  triggers:
                    -
                      label: dev
                      key: /myprefix/my.config.value

我只注意到一件事可能与此相关,从应用程序启动(所有内容都已正确加载)和刷新点查看日志:

2021-11-29 19:51:31.578  INFO [] 34820 --- [           main] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-/myprefix/https://my-config-store-stage.azconfig.io/dev'}, BootstrapPropertySource {name='bootstrapProperties-/application/https://my-config-store-stage.azconfig.io/dev'}]

2021-11-29 19:53:53.694  INFO [] 34820 --- [         task-2] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-/application/https://my-config-store-stage.azconfig.io/dev'}]

似乎在刷新时,Spring 无法找到所有 BootstrapPropertySources,也许这就是为什么没有找到更改的原因。我是不是在某处缺少一些配置来指定这些,或者有人知道这里的问题是什么。谢谢

如果你想启用自动刷新,你应该使用“com.azure.spring:azure-spring-cloud-appconfiguration-config-web:2.1.1”。否则,您必须使用 AzureCloudConfigRefreshrefreshConfiguration 手动触发刷新。参见:https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/appconfiguration/azure-spring-cloud-starter-appconfiguration-config#configuration-refresh

至于ContextRefresher,它在刷新范围内吗?如果不是,则无法更改这些值。

虽然查看您的日志,但您似乎没有发现更改。你能看看这个演示吗?

https://github.com/Azure-Samples/azure-spring-boot-samples/tree/main/appconfiguration/azure-appconfiguration-refresh-sample

运行的说明在这里https://github.com/Azure-Samples/azure-spring-boot-samples/pull/106/files

问题

azure appconfig store 中的更改值正在触发刷新事件(自动使用“web”版本的库或通过手动调用 AppConfigurationRefresh.refreshConfigurations),您可以在日志中看到它,如下所示:

2021-11-29 19:53:03.543  INFO [] 34820 --- [         task-2] c.a.s.c.config.AppConfigurationRefresh   : Configuration Refresh Event triggered by /myprefix/my.config.value
2021-11-29 19:53:53.694  INFO [] 34820 --- [         task-2] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-/application/https://my-config-store-stage.azconfig.io/dev'}]
2021-11-29 19:53:53.719  INFO [] 34820 --- [         task-2] o.s.boot.SpringApplication               : The following profiles are active: messaging,db,dev
2021-11-29 19:53:53.736  INFO [] 34820 --- [         task-2] o.s.boot.SpringApplication               : Started application in 3.347 seconds (JVM running for 158.594)
2021-11-29 19:54:01.265  INFO [] 34820 --- [         task-2] o.s.c.e.event.RefreshEventListener       : Refresh keys changed: []

然而,Spring 引导程序无法找到 PropertySources 中的任何更改,从以下内容可以明显看出:

2021-11-29 19:54:01.265  INFO [] 34820 --- [         task-2] o.s.c.e.event.RefreshEventListener       : Refresh keys changed: []

研究

我发现问题的真正决定因素确实是在应用程序启动时和刷新时找到的 BootstrapPropertySources 之间的差异。

2021-11-29 19:51:31.578  INFO [] 34820 --- [           main] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-/myprefix/https://my-config-store-stage.azconfig.io/dev'}, BootstrapPropertySource {name='bootstrapProperties-/application/https://my-config-store-stage.azconfig.io/dev'}]

2021-11-29 19:53:53.694  INFO [] 34820 --- [         task-2] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-/application/https://my-config-store-stage.azconfig.io/dev'}]

未找到更改的罪魁祸首确实是更新时缺少 BootstrapPropertySource。从我的测试中可以明显看出,所有配置属性都依赖于它们来自的 PropertySource 的名称,如果它丢失,它们将保留其原始的旧值。

问题在于 appconfig 库是 locating/creating BootstrapPropertySources 的方式,并且不区分启动和更新。

以下代码来自 appconfiguration 库,我只提取了导致错误的部分。

public final class AppConfigurationPropertySourceLocator implements PropertySourceLocator {
...
@Override
public PropertySource<?> locate(Environment environment) {
...
    String applicationName = this.properties.getName();
    if (!StringUtils.hasText(applicationName)) {
        applicationName = env.getProperty(SPRING_APP_NAME_PROP);
    }
...
}
...
}

这里的问题是env.getProperty(SPRING_APP_NAME_PROP);启动的时候填的是“spring.application.name”,因为spring 一次加载所有 .yml 文件,但在更新期间不可用。此外,AppConfigurationProperties properties.name 从未在 azure 的任何文档中提及,但对于解决此问题至关重要。

解决方案

如果您使用的是自定义 spring.application.name,也可以在 bootstrap.yml 中包含一些名称,如下所示:

spring:
  cloud:
    azure:
      appconfiguration:
        name: your-name #any value will work
        stores:
          - connection-string: ${connection-string}
            selects:
              - key-filter: '/myprefix/'
                label-filter: dev

            monitoring:
              enabled: true
              refresh-interval: 1s
              triggers:
                -
                  label: dev
                  key: /myprefix/my.config.value

这将使库始终使用属性名称值并避免使用有问题的 spring.application.name 值。