Spring Cloud Config Client

Spring Boot 应用程序可以立即利用 Spring Config Server(或应用程序开发人员提供的其他外部属性源)。它还支持一些与 Environment 更改事件相关的其他有用功能。

Spring Boot Config Data Import

Spring Boot 2.4 引入了一种新方法,即通过 spring.config.import 属性导入配置数据。这现在是绑定到 Config Server 的默认方法。

若要连接到配置服务器,请在 application.properties 中设置以下内容:

application.properties
spring.config.import=optional:configserver:

这将会在 “http://localhost:8888” 的默认位置连接到 Config Server。删除 optional: 前缀会导致 Config Client 在无法连接到 Config Server 时失败。要更改 Config Server 的位置,请设置 spring.cloud.config.uri 或将 URL 添加到 spring.config.import 语句,例如,spring.config.import=optional:configserver:http://myhost:8888。导入属性中的位置优先于 uri 属性。

Spring Boot Config Data 分两步解析配置。首先,它使用 default 配置文件加载所有配置。这样,Spring Boot 就可以收集可能激活其他任何配置文件的所有配置。在收集所有激活的配置文件后,它将加载任何其他活动配置文件的配置。由于此原因,您可能会看到向 Spring Cloud Config Server 发出多个请求以获取配置。这是正常的,并且是 Spring Boot 在使用 spring.config.import 时加载配置时的副作用。在 Spring Cloud Config 的早期版本中,只发出一个请求,但这意味着您无法使用来自 Config Server 的配置激活配置文件。现在,仅包含 default 配置文件的附加请求使得这成为可能。

对于通过 spring.config.import 导入 Spring Boot 配置数据的方法,需要一个 bootstrap 文件(属性或 yaml)。

Config First Bootstrap

要使用旧引导方式连接到 Config Server,必须通过属性或 spring-cloud-starter-bootstrap starter 启用引导。该属性为 spring.cloud.bootstrap.enabled=true。它必须设置为系统属性或环境变量。一旦启用引导,类路径中包含 Spring Cloud Config Client 的任何应用程序将按如下方式连接到 Config Server:当 config client 启动时,它会绑定到 Config Server(通过 spring.cloud.config.uri 引导配置属性)并使用远程属性源初始化 Spring Environment

此行为的最终结果是,所有想要使用 Config Server 的客户端应用程序都需要一个 bootstrap.yml(或环境变量),其中在 spring.cloud.config.uri 中设置了服务器地址(默认为 “http://localhost:8888”)。

Discovery First Lookup

除非你使用 config first bootstrap,否则将需要在配置属性中使用 optional: 前缀设置 spring.config.import 属性。例如, spring.config.import=optional:configserver:

如果您使用 DiscoveryClient 实现,例如 Spring Cloud Netflix 和 Eureka 服务发现或 Spring Cloud Consul,您可以让 Config Server 在发现服务中注册。

如果您希望使用 DiscoveryClient 查找 Config Server,可以通过将 spring.cloud.config.discovery.enabled=true 设为 true(默认值为 false)来实现。例如,在 Spring Cloud Netflix 中,您需要定义 Eureka 服务器地址(例如,在 eureka.client.serviceUrl.defaultZone 中)。使用此选项的价格是启动时额外进行一次网络往返操作,以查找服务注册。好处在于,只要发现服务是一个固定点,Config Server 就可以更改其坐标。默认服务 ID 是 configserver,但您可以通过设置 spring.cloud.config.discovery.serviceId 在客户端上更改它(并在服务器上,以通常的方式为服务设置,例如设置 spring.application.name)。

发现客户端实现都支持某种元数据映射(例如,我们有 Eureka 的 eureka.instance.metadataMap)。Config Server 的一些附加属性可能需要在其服务注册元数据中进行配置,以便客户端可以正确连接。如果 Config Server 使用 HTTP Basic 保护,您可以将凭据配置为 userpassword。此外,如果 Config Server 有上下文路径,您可以设置 configPath。例如,下面的 YAML 文件适用于一个作为 Eureka 客户端的 Config Server:

eureka:
  instance:
    ...
    metadataMap:
      user: osufhalskjrtl
      password: lviuhlszvaorhvlo5847
      configPath: /config

Discovery First Bootstrap Using Eureka And WebClient

如果你使用 Spring Cloud Netflix 中的 Eureka DiscoveryClient,并且还想使用 WebClient 而非 Jersey 或 RestTemplate,你将需要在类路径中包含 WebClient 以及设置 eureka.client.webclient.enabled=true

Config Client Fail Fast

在某些情况下,你可能想要在服务无法连接到 Config Server 时使之启动失败。如果这是期望的行为,请设置引导配置属性 spring.cloud.config.fail-fast=true 以便客户端用一个异常终止。

要使用 spring.config.import 获取类似的功能,只需省略 optional: 前缀即可。

Config Client Retry

如果你预计在你的应用程序启动时 Config Server 可能偶尔不可用,你可以在失败后让它继续尝试。首先,你需要设置 spring.cloud.config.fail-fast=true。然后,你需要将 spring-retryspring-boot-starter-aop 添加到你的类路径中。默认行为是使用 1000ms 的初始回退间隔和后续回退的 1.1 倍指数重试六次。你可以通过设置 spring.cloud.config.retry.* 配置属性来配置这些属性(以及其他属性)。若要使用随机指数回退策略,请将 spring.cloud.config.retry.useRandomPolicy 设置为 true

spring.cloud.config.retry.useRandomPolicytruemax-attemptsinitial-intervalmax-intervalmultiplier 属性甚至在使用随机指数退避策略时仍会生效。有关如何使用它们的详细信息可以在 Spring Retry 中的 ExponentialRandomBackOffPolicyExponentialBackOffPolicy 中找到。

要完全控制重试行为并使用传统引导,请添加一个 ID 为 configServerRetryInterceptor 的类型为 RetryOperationsInterceptor@Bean。Spring Retry 有一个 RetryInterceptorBuilder 支持创建其中一个。

Config Client Retry with spring.config.import

重试适用于 Spring Boot spring.config.import 语句,并且正常属性可用。但是,如果 import 语句位于配置文件中,例如 application-prod.properties,则你将需要一种不同的方式来配置重试。需要在 import 语句的 URL 参数中放置配置。

application-prod.properties
spring.config.import=configserver:http://configserver.example.com?fail-fast=true&max-attempts=10&max-interval=1500&multiplier=1.2&initial-interval=1100"

这将设置 spring.cloud.config.fail-fast=true(注意上面缺少前缀)和所有可用的 spring.cloud.config.retry.* 配置属性。

Locating Remote Configuration Resources

Config Server 从 /{application}/{profile}/{label} 提供属性源,其中客户端应用程序中的默认绑定如下:

  • "application" = ${spring.application.name}

  • “配置文件”= ${spring.profiles.active}(实际上是 Environment.getActiveProfiles()

  • "label" = "master"

设置属性 ${spring.application.name} 时,不要用保留字 application- 为你的应用名称添加前缀,以免在解析正确的属性源时出现问题。

你可以通过设置 spring.cloud.config.(其中 nameprofilelabel)来覆盖所有属性。label 对于回滚到配置的先前版本非常有用。对于默认的 Config Server 实现而言,它可以是 git 标签、分支名称或提交 ID。标签也可以作为逗号分隔的列表提供。在这种情况下,列表中的项将依次尝试,直至有一个成功为止。当在特性分支上操作时,此行为非常有用。例如,你可能想要将 config 标签与你的分支对齐,但将其设为可选(在这种情况下,使用 spring.cloud.config.label=myfeature,develop)。

Specifying Multiple URLs for the Config Server

为了在你部署了多个 Config Server 实例并且预计其中的一个或多个实例不可用或时不时无法处理请求时(例如 Git 服务器宕机)确保高可用性,你可以指定多个 URL(在 spring.cloud.config.uri 属性下以逗号分隔的列表)或让你的所有实例在服务注册表中注册,例如 Eureka(如果使用 Discovery-First Bootstrap 模式)。

spring.cloud.config.uri 下列出的 URL 将按列出的顺序尝试。默认情况下,Config Client 将尝试从每个 URL 获取属性,直到尝试成功为止,以确保高可用性。

但是,如果你只想在 Config Server 未运行时(即,应用程序已经退出)或连接超时时确保高可用性,请将 spring.cloud.config.multiple-uri-strategy 设置为 connection-timeout-only。(spring.cloud.config.multiple-uri-strategy 的默认值为 always。)例如,如果 Config Server 返回 500(内部服务器错误)响应或者 Config Client 从 Config Server 接收 401(由于凭证错误或其他原因),则 Config Client 不会尝试从其他 URL 获取属性。400 错误(可能除外 404)表示的是用户问题,而不是可用性问题。请注意,如果将 Config Server 设置为使用 Git 服务器并且对 Git 服务器的调用失败,则可能会发生 404 错误。

可以在单个 spring.config.import 键下指定多个位置,而不是 spring.cloud.config.uri。位置将按照定义它们的顺序进行处理,后来的导入优先。但是,如果 spring.cloud.config.fail-fasttrue,则无论出于何种原因,如果第一个 Config Server 调用不成功,Config Client 将失败。如果 fail-fastfalse,它将尝试所有 URL,直到一个调用成功,无论失败原因如何。(在 spring.config.import 下指定 URL 时,spring.cloud.config.multiple-uri-strategy 并不适用。)

如果你在 Config Server 中使用 HTTP 基本安全,则现在只支持每个 Config Server 的身份验证凭证(前提是你将凭证嵌入 spring.cloud.config.uri 属性下指定的每个 URL)。如果你使用其他任何种类的安全机制,则你(当前)无法支持每个 Config Server 的身份验证和授权。

Configuring Timeouts

如果你想要配置超时阈值:

  • 可以使用属性 spring.cloud.config.request-read-timeout 配置读取超时。

  • 可以使用属性配置连接超时`spring.cloud.config.request-connect-timeout`。

Security

如果你在服务器上使用 HTTP 基本安全,则客户端需要知道密码(如果不是默认的,则还需要用户名)。你可以通过 config server URI 或单独的用户名和密码属性指定用户名和密码,如下例所示:

spring:
  cloud:
    config:
     uri: https://user:secret@myconfig.mycompany.com

以下示例演示了传递相同信息的另一种方法:

spring:
  cloud:
    config:
     uri: https://myconfig.mycompany.com
     username: user
     password: secret

spring.cloud.config.passwordspring.cloud.config.username 值会覆盖 URI 中提供的所有内容。

如果你在 Cloud Foundry 上部署你的应用,通过服务凭证(例如在 URI 中,因为它不需要在配置文件中)是提供密码的最佳方式。以下示例在本地以及在 Cloud Foundry 上名为 configserver 的用户提供的服务中适用:

spring:
  cloud:
    config:
     uri: ${vcap.services.configserver.credentials.uri:http://user:password@localhost:8888}

如果 config server 需要客户端侧 TLS 证书,你可以通过属性配置客户端侧 TLS 证书和信任存储,如下例所示:

spring:
  cloud:
    config:
      uri: https://myconfig.myconfig.com
      tls:
        enabled: true
        key-store: <path-of-key-store>
        key-store-type: PKCS12
        key-store-password: <key-store-password>
        key-password: <key-password>
        trust-store: <path-of-trust-store>
        trust-store-type: PKCS12
        trust-store-password: <trust-store-password>

spring.cloud.config.tls.enabled 需要为 true 才能启用 config 客户端侧 TLS。当省略 spring.cloud.config.tls.trust-store 时,将使用 JVM 默认信任存储。spring.cloud.config.tls.key-store-typespring.cloud.config.tls.trust-store-type 的默认值为 PKCS12。当省略密码属性时,则假定为空密码。

如果您使用其他形式的安全,则可能需要通过将 ConfigServicePropertySourceLocator 添加到 xref:client.adoc#custom-rest-template[provide a RestTemplate 中(例如在引导上下文中获取它并注入它)来保护 ConfigServicePropertySourceLocator

Health Indicator

Config Client 会提供一个 Spring Boot 健康指示符,它尝试从 Config Server 加载配置。可通过设置 health.config.enabled=false 禁用健康指示符。出于性能原因,响应也会被缓存。默认的缓存生存期为 5 分钟。要更改该值,请设置 health.config.time-to-live 属性(以毫秒为单位)。

Providing A Custom RestTemplate

在某些情况下,您可能需要自定客户端到 Config Server 的请求。通常,这样做涉及传递特殊的“Authorization”首部以认证到服务器的请求。

Providing A Custom RestTemplate Using Config Data

使用 Config Data 时提供自定义 RestTemplate

  1. 创建一个实现`BootstrapRegistryInitializer`的类。[source, java] .CustomBootstrapRegistryInitializer.java

public class CustomBootstrapRegistryInitializer implements BootstrapRegistryInitializer {

	@Override
	public void initialize(BootstrapRegistry registry) {
		registry.register(RestTemplate.class, context -> {
			RestTemplate restTemplate = new RestTemplate();
			// Customize RestTemplate here
			return restTemplate;
		});
	}

}
  1. 在`resources/META-INF`中,创建一个名为`spring.factories`的文件,并指定您的自定义配置,如下例所示:[source, properties] .spring.factories

org.springframework.boot.BootstrapRegistryInitializer=com.my.config.client.CustomBootstrapRegistryInitializer

Providing A Custom RestTemplate Using Bootstrap

使用引导时提供自定义 RestTemplate

  1. 使用`PropertySourceLocator`的实现创建一个新的配置Bean,如下例所示:[source, java] .CustomConfigServiceBootstrapConfiguration.java

@Configuration
public class CustomConfigServiceBootstrapConfiguration {
    @Bean
    public ConfigServicePropertySourceLocator configServicePropertySourceLocator() {
        ConfigClientProperties clientProperties = configClientProperties();
       ConfigServicePropertySourceLocator configServicePropertySourceLocator =  new ConfigServicePropertySourceLocator(clientProperties);
        configServicePropertySourceLocator.setRestTemplate(customRestTemplate(clientProperties));
        return configServicePropertySourceLocator;
    }
}

为了简化添加 Authorization 标头的方法,可以使用 spring.cloud.config.headers.* 属性。

  1. 在`resources/META-INF`中,创建一个名为`spring.factories`的文件,并指定您的自定义配置,如下例所示:[source, properties] .spring.factories

org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration

Vault

使用 Vault 作为 Config Server 的后端时,客户端需要为服务器提供令牌,以从 Vault 检索值。可通过在 bootstrap.yml 中设置 spring.cloud.config.token 来在客户端中提供令牌,如以下示例所示:

spring:
  cloud:
    config:
      token: YourVaultToken

Nested Keys In Vault

Vault 支持将键嵌套到存储在 Vault 中的值中,如以下示例所示:

echo -n '{"appA": {"secret": "appAsecret"}, "bar": "baz"}' | vault write secret/myapp -

此命令会将 JSON 对象写入您的 Vault。要在 Spring 中访问这些值,您需要使用传统点(.)注解,如以下示例所示:

@Value("${appA.secret}")
String name = "World";

上述代码会将 name 变量的值设置为 appAsecret

AOT and Native Image Support

4.0.0 起,Spring Cloud Config Client 支持 Spring AOT 转换和 GraalVM 本机映像。

config first bootstrap(带 spring.config.use-legacy-processing=true)不支持 AOT 和本地 image。

刷新范围不受本机映像支持。如果您打算以本机映像形式运行 Config 客户端应用程序,请确保将 spring.cloud.refresh.enabled 属性设置为 false

在构建一个包含 Spring Cloud 配置客户端的项目时,你必须确保它连接到的配置数据源(例如 Spring Cloud 配置服务器、 领事、Zookeeper、Vault 等)可用。例如,如果你从 Spring Cloud 配置服务器检索配置数据,请确保其实例正在运行,并且在配置客户端设置中指定的端口上可用。这是必要的,因为应用程序上下文在构建时经过优化,并且需要解析目标环境。

由于在 AOT 和原生模式下,配置正在被处理并且上下文在构建时正在被优化,因此任何会影响 Bean 创建的属性(例如在引导上下文中使用的属性)都应在构建时和运行时设置为相同的值,以避免意外行为。

由于在从原生映像启动时,配置客户端连接到正在运行的数据源(例如配置服务器),因此快速启动时间会因进行此网络通信所需的时间而减慢。

Appendices

Observability metadata

Observability metadata

Observability - Metrics

Observability - Metrics

下面您可以找到此项目声明的所有指标的列表。

Environment Repository

围绕 EnvironmentRepository 创建观察。

度量名称 spring.cloud.config.environment.find(由惯例类 org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention 定义)。类型 计时器

度量名称 spring.cloud.config.environment.find.active(由惯例类 org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention 定义)。类型 长任务计时器

在 Observation 启动后添加的 KeyValues 可能会缺失于 *.active 指标。

Micrometer 内部使用 nanoseconds 作为基本单位。但是,每个后端决定实际基本单位。(例如,Prometheus 使用秒)

封闭类 org.springframework.cloud.config.server.environment.DocumentedConfigObservation 的完全限定名称。

所有标签都必须带有 spring.cloud.config.environment 前缀!

Table 1. Low cardinality Keys

Name

Description

spring.cloud.config.environment.application (required)

正在查询其属性的应用程序名称。

spring.cloud.config.environment.class (required)

Implementation of the EnvironmentRepository.

spring.cloud.config.environment.label (required)

正在查询其属性的标签。

spring.cloud.config.environment.profile (required)

正在查询其属性的应用程序名称。

Observability - Spans

  • spring.cloud.config.environment.application:正在查询属性的应用程序名称。

  • spring.cloud.config.environment.label:正在查询属性的标签。

  • spring.cloud.config.environment.profile:应用程序名称。

Observability - Spans

下面您可以找到此项目声明的所有 span 的列表。

Environment Repository Span

围绕 EnvironmentRepository 创建观察。

跨度名称 spring.cloud.config.environment.find(由惯例类 org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention 定义)。

封闭类 org.springframework.cloud.config.server.environment.DocumentedConfigObservation 的完全限定名称。

所有标签都必须带有 spring.cloud.config.environment 前缀!

Table 2. Tag Keys

Name

Description

spring.cloud.config.environment.application (required)

正在查询其属性的应用程序名称。

spring.cloud.config.environment.class (required)

Implementation of the EnvironmentRepository.

spring.cloud.config.environment.label (required)

正在查询其属性的标签。

spring.cloud.config.environment.profile (required)

正在查询其属性的应用程序名称。