Skip to content

配置中心

shedfreewu edited this page Dec 4, 2024 · 9 revisions

目录

模块简介

配置中心模块是 Spring Cloud Tencent 最核心的模块之一,实现了 Spring Cloud PropertySourceLocator SPI 接口(PolarisConfigFileLocator.java)。

在应用启动 Bootstrap 阶段,Spring Cloud 会调用 PolarisConfigFileLocator 从 Polaris 服务端获取配置文件并加载到 Spring 上下文里。通过 Spring Boot 标准的 @Value@ConfigurationProperties 注解即可获取配置内容。

动态配置刷新能力,1.6.0 版本之前通过 Spring Cloud 标准的 @RefreshScope 机制实现。 1.6.0 版本之后,通过反射的方式实现。反射的方式不用重新构建 bean 对象,影响面更小、性能更优。

注意:

  1. 由于 Spring Cloud PropertySourceLoader SPI 是在 Bootstrap 阶段调用,所以 Polaris Config 相关的配置内容(例如Polaris 服务地址)需要放在 bootstrap.yml 文件里,而不能放在 application.yml 文件里,否则会初始化失败。
  2. 如果开发者原本的服务名( spring.application.name )配置在 application.ymlapplication-*.ymlapplication.propertiesapplication-*.properties 内,使用 Spring Cloud Tencent Config 的功能时,需要将 spring.application.name 配置在 bootstrap.yml 内,或者在 bootstrap.yml 手动配置 spring.cloud.polaris.service 以指定文件分组名。

快速入门

本章节将介绍如何在 Spring Cloud 项目中使用 Spring Cloud Tencent Config 的功能。

完整 Example 代码请参考:quickstart-example

第一步:引入 Polaris 服务端

请参考 安装北极星服务端

第二步:引入动态配置依赖

  1. 参考 Spring Cloud Tencent 版本管理 文档获取最新的版本号,引入 Spring Cloud Tencent Bom

注意: Spring Cloud 、 Spring Boot 、 Spring Framework 之间有严格的版本对应关系,在 Spring Cloud Tencent 版本管理 文档中有详细罗列版本兼容性关系。请您在引入 Spring Cloud Tencent 版本时,根据项目 Spring Boot 和 Spring Framework 的版本,选择合适的 Spring Cloud Tencent 版本。

例如:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.tencent.cloud</groupId>
            <artifactId>spring-cloud-tencent-dependencies</artifactId>
            <version>${the.latest.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  1. 引入 Spring Cloud Tencent Config Starter

方式一:只引入 spring-cloud-starter-tencent-polaris-config

<dependency>
    <groupId>com.tencent.cloud</groupId>
    <artifactId>spring-cloud-starter-tencent-polaris-config</artifactId>
</dependency>

方式二:通过 spring-cloud-starter-tencent-all 引入 sct 所有 starters

<dependency>
    <groupId>com.tencent.cloud</groupId>
    <artifactId>spring-cloud-starter-tencent-all</artifactId>
</dependency>

如果使用 Spring Cloud 2021 及以上版本,还需要添加如下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

第三步:增加相关配置文件

在您项目的 bootstrap.yml 配置文件中加入以下配置内容,注意一定要放在 bootstrap.yml 里。因为应用启动强依赖配置,所以 Spring Cloud Config 是在 Bootstrap 阶段加载配置文件,所以需要把北极星相关的配置放在 bootstrap.yml 里。

bootstrap.yml 核心配置内容为配置北极星服务端地址以及注入的配置文件信息。

1. 配置 Polaris 配置中心地址

如果您使用的北极星配置中心和注册中心是同一套北极星集群,则只需配置 spring.cloud.polaris.address 即可。

如果您部署了两套北极星集群,分别用于注册中心和配置中心,则 spring.cloud.polaris.address 用于指定注册中心集群的地址,spring.cloud.polaris.config.address 用于指定配置中心的地址。

如下所示:

spring:
  application:
    name: ${application.name}
  cloud:
    polaris:
      address: grpc://${修改为第一步部署的 Polaris 服务地址}:8091 # 必填
      namespace: default # 全局 namespace 参数
      config:
        address: grpc://${独立的配置中心}:8093 # 选填,只有在配置中心和注册中心是两个不同的地址时才需要配置
        auto-refresh: true # 选填,当配置发布后,动态刷新 Spring 上下文,默认值为 true

2. 注入配置文件

我们推荐的最佳实践是在北极星管控端创建一个名为当前应用名( ${spring.application.name}) 的配置分组,Spring Cloud Tencent Config 会自动注入当前应用名分组下的

  • application-${activeProfile}.properties
  • application-${activeProfile}.yml
  • application-${activeProfile}.yaml
  • application.properties
  • application.yml
  • application.yaml
  • bootstrap-${activeProfile}.properties
  • bootstrap-${activeProfile}.yml
  • bootstrap-${activeProfile}.yaml
  • bootstrap.properties
  • bootstrap.yml
  • bootstrap.yaml

加载顺序依次从上到下,即越先加载的配置,优先级越高。与此同时,远端配置优先级大于本地配置优先级。优先级高的配置覆盖优先级低的配置。

自动注入以上配置文件符合 Spring Boot 的规范,能够满足绝大部分应用场景了。

只有当您需要注入额外自定义的配置文件时,才需要在 bootstrap.yml 里配置 spring.cloud.polaris.config.groups,如下所示:

spring:
  cloud:
    polaris:
      config:
        groups:
          - name: ${spring.application.name} # 选填,注入自定义配置的配置分组
            files: [ "config/application.properties", "config/bootstrap.yml" ] # 注入自定义配置文件列表,当 key 冲突时,排在前面的配置文件优先级高于后面

第四步:代码里使用配置

1. 通过 @Value 注入

@Value("${timeout:1000}")
private int timeout;

2. 通过 @ConfigurationProperties 注入

@Component
@ConfigurationProperties(prefix = "teacher")
@RefreshScope //如果使用反射模式,则不需要加这个注解
public class Person {

	private String name;

	private int age;

	String getName() {
		return name;
	}

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

	int getAge() {
		return age;
	}

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

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

}

第五步:在北极星控制台添加配置文件

1. 创建 Namespace

Namespace 为北极星里核心的概念,通过 Namespace 逻辑隔离资源,例如通常用于标识不同的环境、不同的集群。

注意这里需要和应用配置中的命名空间保持一致!

2. 创建配置文件分组

北极星的配置文件分组概念为一组配置文件的集合,推荐把应用名作为一个分组名,例如在我们的示例中,新建一个 polaris-config-example 的分组。 把 polaris-config-example 应用的配置文件都放在polaris-config-example 分组下,这样便于配置管理。

3. 创建并发布配置文件

北极星配置中心的控制台,配置文件名可以通过 / 来按树状目录结构展示,树状结构可以清晰的管理配置文件。例如一个应用下分不同的模块,每个模块都有独立的一组配置文件,则可以创建 module1/file1.properties, module1/file2.yaml, module2/file3.yaml

注意:配置文件名强烈建议带文件后缀,例如 .properties .yaml .yml .json 等。因为客户端会通过文件名后缀来解析文件内容,如果客户端发现不认识的后缀名则默认当做 .properties 文件处理。

配置好的实例如下图所示:

image

第六步:启动应用

到此接入 Spring Cloud Tencent Config 即已完成。

第七步:实现动态刷新配置能力

Spring Cloud Tencent 1.7.0(不包含) 之前的版本通过 Spring Cloud 标准的 @RefreshScope 实现配置动态刷新。@RefreshScope 存在以下局限性:

  1. 每次刷新配置,需要重新构建整个 Spring Context 重建 Bean,影响面非常大
  2. 代码里层面需要引入 @RefreshScope 注解

1.7.1 版本(包含)之后,SCT 优化了动态刷新的实现方式。

刷新 @Value 属性

应用启动时扫描所有的 Bean,构建 @Value 属性对应的 Bean 的映射关系。当属性配置更新时,找到所有的待更新的 Bean 并利用 Java 的反射机制更新属性。

刷新 @ConfigurationProperties 配置类

相比于 @RefreshScope 重建所有的 Bean,优化之后的刷新机制只需要重建更新的配置对应的 @ConfigurationProperties Bean,影响面更小。实现原理请看 PolarisRefreshAffectedContextRefresherAffectedConfigurationPropertiesRebinder

如果您想使用传统的 @RefreshScope 方式刷新配置,可以配置 spring.cloud.polaris.config.refresh-type=refresh_context

关闭动态刷新能力

bootstrap.yml 里配置 spring.cloud.polaris.config.auto-refresh=false

拓展使用

自定义配置监听器

方式一:使用 SCT 的事件回调机制

1.6.0 版本(包含)之后,新增了配置变更回调事件能力。可通过注解@PolarisConfigKVFileChangeListener实现针对指定的配置属性名称或者属性前缀进行监听,配置发生变更时会触发方法回调。

注意:目前只支持 KV 结构的配置文件监听

@Component
public final class PersonConfigChangeListener {

	/**
	 * PolarisConfigKVFileChangeListener Example .
	 * @param event instance of {@link ConfigChangeEvent}
	 */
	@PolarisConfigKVFileChangeListener(interestedKeyPrefixes = "teacher")
	public void onChange(ConfigChangeEvent event) {
		Set<String> changedKeys = event.changedKeys();

		for (String changedKey : changedKeys) {
			System.out.printf("%s = %s \n", changedKey, event.getChange(changedKey));
		}
	}

}

方式二:使用 Spring Boot 的事件机制

1.8.0 版本之后,可通过 Spring Boot 标准事件机制来监听配置的变更,代码如下所示:

@Component
public class PersonConfigChangeSpringListener implements ApplicationListener<ConfigChangeSpringEvent> {

	@Override
	public void onApplicationEvent(ConfigChangeSpringEvent event) {
		for (String key : event.changedKeys()) {
			System.out.println("Change Key = " + key + ", info = " + event.getChange(key));
		}
	}
}

支持 Spring Config Data

SCT 2021 及以上版本支持了标准的 Spring Config Data 方式注入配置文件。同样的 SCT 默认会注入 application.ymlapplication-${activeProfile}.ymlbootstrap.ymlbootstrap-${activeProfile}.yml,除此之外可以通过以下配置注入额外的配置文件。

spring
  config:
    import:
      - optional:polaris
      - optional:polaris:test.yml
      - optional:polaris:configdataexample:test.yml
      - optional:polaris:config/bootstrap.yml

格式说明

optional:${数据来源,固定值 polaris}:${配置分组名:缺省值为当前应用名}:${配置文件名}

本地开发模式(自1.8.0 版本)

在某些场景下,期望使用本地的配置文件而不是从远端的北极星服务获取配置。例如:

  1. 当前开发环境处于一个没有网络的环境,飞机上、游轮上等
  2. 避免修改北极星服务端的配置从而影响其它环境的配置

1.8.0 版本之后,动态配置模块将会在本地 ./polaris/backup/config 目录下缓存从北极星服务端获取的所有配置文件。SCT 配置 spring.cloud.polaris.config.data-source=local 参数即可切换到本地模式(从 ./polaris/backup/config 读取配置)。此时如果您需要修改配置,则只需要修改 ./polaris/backup/config 下的配置文件即可。

注意:修改配置文件时需要同时增加版本号,因为需要通过版本号来做乐观锁,只有在版本号增大时,才认为配置文件有修改

另外,您需要自定义本地文件目录可以通过 spring.cloud.polaris.config.local-file-root-path 配置项指定根目录。

Actuator Endpoint

Spring Cloud Tencent 扩展了 Spring Boot 标准的 Actuator 能力,通过 Actuator 接口,可以实时查询当前运行实例内存里配置文件内容,便于排查问题。详细可以参考: Actuator Endpoint 扩展

配置刷新方式自动识别与更新(1.12.0+)

开发者使用@RefreshScope 时,如果指定配置的刷新方式为 reflect(反射)时,会自动将其更新为 refresh_context(重载bean)的方式。并打印WARN日志:

2023-09-12T11:55:56.375+08:00  WARN 37516 --- [           main] PolarisConfigRefreshOptimizationListener : Detected that the bean [scopedTarget.configController] is using @RefreshScope annotation, but the config refresh type is still [reflect]. [SCT] will automatically switch to [refresh_context].

单配置项刷新

Spring Cloud Hoxton 版本从 2.0.0.0-Hoxton.SR12-RC1 开始支持,其他 Spring Cloud 版本在支持中

2.0.0.0 版本开始,配置刷新支持细粒度区分,当变更配置 key 列表涉及 @RefreshScope 相关的 key。才通过重新构建整个 Spring Context 的方式重建 Bean,否则只需要反射更新。具体行为如下:

  • refresh_context 刷新方式(默认)

    • 有 RefreshScope 相关的配置 key
      • ConfigurationProperties:反射更新
      • Refresh Scope + @Value:重建对象
      • 纯 @Value:不动态更新
    • 无 RefreshScope 相关的配置 key
      • ConfigurationProperties :反射更新
      • Refresh Scope + @Value:不刷新
      • 纯 @Value: 不动态更新
  • reflect 刷新方式

    • 有 RefreshScope 相关的配置 key
      • ConfigurationProperties:反射更新
      • Refresh Scope + @Value:重建对象
      • 纯 @Value:反射更新
    • 无 RefreshScope 相关的配置 key
      • ConfigurationProperties:反射更新
      • Refresh Scope + @Value:不刷新
      • 纯 @Value:反射更新

RefreshScope 相关的配置 key 的类型

  1. class 注解定义 bean (@RestController、@Service、 @Configuration 等),@RefreshScope 在 class 上。该类下所有 @Value 注解涉及的配置 key 都是 RefreshScope 相关的配置 key
@Component
@RefreshScope
private static class ValueTest {
	@Value("${timeout:1000}")
	private int timeout;
	// ignore setter getter
}
  1. 通过 @Bean 和 @RefreshScope 定义 bean,bean 的类所有 @Value 注解涉及的配置 key 都是 RefreshScope 相关的配置 key
@Configuration
public class TestConfig {
	@Bean
	@RefreshScope
	public TestBean testBean() {
		return new TestBean();
	}
}

class TestBean {
	@Value("${test.bean.name:}")
	private String name;
	// ignore setter getter
}
  1. 通过 @Bean 和 @RefreshScope 定义 bean,参数有 @Value 标注。@Value 注解涉及的配置 key 是 RefreshScope 相关的配置 key
@Configuration
public class TestConfig {
	@Bean
	@RefreshScope
	public TestBean testBean(@Value("${test.param.name:}") String name) {
		return new TestBean(name);
	}
}
  1. 通过 @Bean 和 @RefreshScope 定义 bean,bean 的类的 setter 方法存在 @Value 注解。 @Value 注解涉及的配置 key 都是 RefreshScope 相关的配置 key
@Configuration
public class TestConfig {
	@Bean
	@RefreshScope
	public TestBean testBean() {
		return new TestBean();
	}
}
class TestBean {
	private int timeout;
	@Value("${test.bean.timeout:0}")
	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}
	// ignore getter
}
  1. 通过 @Bean 和 @RefreshScope 定义 bean,参数为 ConfigurationProperties 对象。ConfigurationProperties 对象涉及的配置 key 都是 RefreshScope 相关的配置 key
@Configuration
public class TestConfig {
	@Bean
	@RefreshScope
	public TestBean testBean(TestBeanProperties testBeanProperties) {
		return new TestBean(testBeanProperties.getName());
	}
}
@Component
@ConfigurationProperties("test.properties")
class TestBeanProperties {
	private String name;
	private HashMap<String, String> map;
	private ArrayList<String> list;
	// ignore setter getter
}
  1. 通过 @Bean 和 @RefreshScope 定义 bean,使用类里的 ConfigurationProperties 对象。ConfigurationProperties 对象涉及的配置 key 都是 RefreshScope 相关的配置 key
@Configuration
public class TestConfig {
	@Autowired
	private TestBeanProperties testBeanProperties;
	@Bean
	@RefreshScope
	public TestBean testBean() {
		return new TestBean(testBeanProperties.getName());
	}
}

完整的配置参数

配置项Key 起始版本 默认值 是否必填 配置项说明
spring.cloud.polaris.config.enabled true 是否开启配置模块
spring.cloud.polaris.config.address 北极星服务端地址,可不填。当配置中心和注册中心为不同的地址时候才需要填写
spring.cloud.polaris.config.port 8093 北极星配置中心的端口号,默认为 8093
spring.cloud.polaris.config.auto-refresh true 是否动态更新配置
spring.cloud.polaris.config.groups 从北极星服务端获取自定义的配置文件
spring.cloud.polaris.config.connect-remote-server true 是否连接到远程北极星配置中心服务端,当没有网络环境或者无北极星服务端时可关闭
spring.cloud.polaris.config.refresh-type 1.7.0 reflect 动态刷新配置的实现方式。
refresh_context 为 Spring Cloud 默认的方式,
reflect 为 SCT 实现的通过反射的机制实现的,优点是无需重建 Bean
spring.cloud.polaris.config.shutdown-if-connect-to-config-server-failed 1.7.0 true 应用启动时检查配置中心的后端连接,如果连接配置中心失败,是否需要终止应用启动(true 为终止启动)
spring.cloud.polaris.config.data-source 1.8.0 polaris 动态配置数据源类型,当前支持 polaris 和 local 两种模式,默认为 polaris。
- polaris: 从北极星服务端获取配置文件。
- local: 从本地磁盘读取配置文件
spring.cloud.polaris.config.local-file-root-path 1.8.0 ./polaris/backup/config spring.cloud.polaris.config.data-source=local 时,可设置本地磁盘读取配置文件根目录
spring.cloud.polaris.config.crypto.enabled 1.13.0 true 是否开启配置加解密,参考文档
Clone this wiki locally