Spring Cloud Config 客户端

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

Spring Boot配置数据导入

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

要可选地连接到配置服务器,请在 application.properties 中进行如下设置

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

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

Spring Boot 配置数据通过两步过程解析配置。首先,它使用 default 配置文件加载所有配置。这允许 Spring Boot 收集所有可能激活任何其他配置文件的配置。在收集了所有已激活的配置文件后,它将为活动配置文件加载任何额外的配置。因此,您可能会看到多次向 Spring Cloud Config Server 发出请求以获取配置。这是正常的,是 Spring Boot 在使用 spring.config.import 时加载配置的方式的副作用。在 Spring Cloud Config 的先前版本中,只发出一个请求,但这表示您无法从 Config Server 激活配置文件。现在,额外使用 default 配置文件的请求使得这成为可能。

通过spring.config.import的Spring Boot配置数据导入方法不需要bootstrap文件(properties或yaml)。

配置优先启动

要使用传统的启动方式连接到 Config Server,必须通过属性或 spring-cloud-starter-bootstrap 启动器启用启动。该属性是 spring.cloud.bootstrap.enabled=true。它必须设置为系统属性或环境变量。一旦启用了启动,任何类路径上带有 Spring Cloud Config Client 的应用程序都将按以下方式连接到 Config Server:当配置客户端启动时,它会绑定到 Config Server(通过 spring.cloud.config.uri 启动配置属性)并使用远程属性源初始化 Spring Environment

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

服务发现优先查找

除非您正在使用配置优先启动,否则您的配置属性中需要有一个带有 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(默认为 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

使用 Eureka 和 WebClient 进行服务发现优先启动

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

配置客户端快速失败

在某些情况下,如果服务无法连接到 Config Server,您可能希望启动失败。如果这是期望的行为,请将启动配置属性 spring.cloud.config.fail-fast=true 设置为使客户端因异常而停止。

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

配置客户端重试

如果您预期在应用程序启动时配置服务器可能偶尔不可用,您可以在失败后使其继续尝试。首先,您需要设置 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.useRandomPolicytrue 时,max-attemptsinitial-intervalmax-intervalmultiplier 属性即使在使用随机指数退避策略时仍然有效。有关它们如何使用的详细信息可以在 Spring Retry 中的 ExponentialRandomBackOffPolicyExponentialBackOffPolicy 中找到。
要完全控制重试行为并使用旧版启动,请添加一个 ID 为 configServerRetryInterceptorRetryOperationsInterceptor 类型的 @Bean。Spring Retry 有一个 RetryInterceptorBuilder 支持创建此类。

使用 spring.config.import 的配置客户端重试

重试功能适用于 Spring Boot 的 spring.config.import 语句和常规属性。但是,如果导入语句位于配置文件中,例如 application-prod.properties,则您需要一种不同的方式来配置重试。配置需要作为 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.* 配置属性。

定位远程配置资源

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

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

  • "profile" = ${spring.profiles.active}(实际上是 Environment.getActiveProfiles()

  • "label" = "master"

设置属性 ${spring.application.name} 时,请勿使用保留字 application- 作为应用名前缀,以防止解析正确属性源时出现问题。

您可以通过设置 spring.cloud.config.*(其中 *nameprofilelabel)来覆盖所有这些属性。label 对于回滚到以前的配置版本非常有用。对于默认的 Config Server 实现,它可以是 git 标签、分支名称或提交 ID。Label 也可以以逗号分隔列表的形式提供。当在功能分支上工作时,此行为可能很有用。例如,您可能希望将配置标签与您的分支对齐,但使其可选(在这种情况下,使用 spring.cloud.config.label=myfeature,develop)。

请求多个标签

在 Spring Cloud Config 4.2.0 之前,如果您将 spring.cloud.config.label 设置为逗号分隔的标签列表,Config Client 将通过向 Config Server 发出请求来尝试每个标签,直到找到一个可用的标签。这意味着如果找到了第一个标签,则不会尝试后续标签。

从 Spring Cloud Config 4.2.0 开始,如果您将 spring.cloud.config.label 设置为逗号分隔的标签列表 **并且** 设置 spring.cloud.config.send-all-labelstrue,则 Config Client 将向 Config Server 发送一个包含逗号分隔标签列表的单个请求,并且如果 **Config Server 使用 4.2.0 或更高版本**,它将返回一个包含所有标签的属性源的单个响应。

spring.cloud-config.send-all-labels 设置为 true,将 spring.cloud.config.label 设置为逗号分隔的标签列表,并使用低于 4.2.0 版本的 Config Server 将导致意外行为,因为 Config Server 将尝试查找与逗号分隔列表值匹配的标签,并且不会尝试拆分标签。

通过在单个请求中发送所有标签,您可以减少向 Config Server 发出的请求数量。

spring.cloud.config.send-all-labels 默认为 false,因此旧的行为仍然是默认行为,并且它还保持与旧版本 Config Server 的兼容性。

为配置服务器指定多个 URL

当您部署了多个 Config Server 实例,并且预计一个或多个实例会时不时地不可用或无法响应请求(例如,如果 Git 服务器宕机),为了确保高可用性,您可以指定多个 URL(作为 spring.cloud.config.uri 属性下的逗号分隔列表),或者让所有实例在像 Eureka 这样的服务注册中心注册(如果使用服务发现优先启动模式)。

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(Internal Server Error)响应或 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 不适用。)

如果您的配置服务器使用 HTTP 基本安全,目前只有在您将凭据嵌入到 spring.cloud.config.uri 属性下指定的每个 URL 中时,才能支持每个配置服务器的身份验证凭据。如果您使用任何其他类型的安全机制,您(目前)无法支持每个配置服务器的身份验证和授权。

配置超时

如果您想配置超时阈值

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

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

配置字符集

如果您希望配置服务器提供特定字符集的资源,您需要通过 charset 应用它。

spring:
  cloud:
    config:
      charset: UTF-8

字符集配置属性定义为 java.nio.charset.Charset

安全

如果服务器使用 HTTP Basic 安全,客户端需要知道密码(如果不是默认值,还需要知道用户名)。您可以通过配置服务器 URI 或通过单独的用户名和密码属性指定用户名和密码,如以下示例所示

spring:
  cloud:
    config:
     uri: https://user:[email protected]

以下示例展示了传递相同信息的另一种方式

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}

如果配置服务器需要客户端 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 才能启用配置客户端 TLS。当省略 spring.cloud.config.tls.trust-store 时,将使用 JVM 默认信任存储。spring.cloud.config.tls.key-store-typespring.cloud.config.tls.trust-store-type 的默认值为 PKCS12。当省略密码属性时,假定为空密码。

如果您使用其他形式的安全性,您可能需要 ConfigServicePropertySourceLocator 提供一个 RestTemplate(例如,通过在引导上下文中获取并注入它)。

健康指标

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

提供自定义 RestTemplate

在某些情况下,您可能需要自定义从客户端向配置服务器发出的请求。通常,这涉及传递特殊的 Authorization 头以对服务器请求进行身份验证。

使用配置数据提供自定义 RestTemplate

使用配置数据时提供自定义 RestTemplate

  1. 创建一个实现 BootstrapRegistryInitializer 的类

    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;
    		});
    	}
    
    }
  2. resources/META-INF 中,创建一个名为 spring.factories 的文件并指定您的自定义配置,如以下示例所示

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

使用 Bootstrap 提供自定义 RestTemplate

在使用 Bootstrap 时提供自定义 RestTemplate

  1. 创建一个新的配置 bean,其中包含 PropertySourceLocator 的实现,如以下示例所示

    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.* 属性代替。
  2. resources/META-INF 中,创建一个名为 spring.factories 的文件并指定您的自定义配置,如以下示例所示

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

Vault

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

spring:
  cloud:
    config:
      token: YourVaultToken

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 和 Native Image 支持

4.0.0 版本开始,Spring Cloud Config Client 支持 Spring AOT 转换和 GraalVM 本机镜像。

对于配置优先启动(使用 spring.config.use-legacy-processing=true)不支持 AOT 和本地镜像。
原生镜像不支持刷新范围。如果你将把你的配置客户端应用程序作为原生镜像运行,请确保将 spring.cloud.refresh.enabled 属性设置为 false
在构建包含 Spring Cloud Config Client 的项目时,您必须确保它连接到的配置数据源(例如,Spring Cloud Config Server、Consul、Zookeeper、Vault 等)可用。例如,如果您从 Spring Cloud Config Server 检索配置数据,请确保其实例正在运行并可在 Config Client 设置中指示的端口上访问。这是必要的,因为应用程序上下文在构建时进行了优化,并且需要解析目标环境。
由于在 AOT 和原生模式下,配置正在被处理并且上下文在构建时被优化,因此任何会影响 bean 创建的属性(例如在引导上下文中使用的属性)在构建时和运行时都应设置为相同的值,以避免意外行为。
由于 Config Client 在从本机镜像启动时会连接到正在运行的数据源(例如 Config Server),因此快速启动时间将因网络通信所需的时间而减慢。

附录

可观测性元数据

可观测性 - 指标

以下是本项目声明的所有指标列表。

环境仓库

围绕 EnvironmentRepository 创建的观测。

指标名称 spring.cloud.config.environment.find(由约定类 org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention 定义)。类型 timer

指标名称 spring.cloud.config.environment.find.active(由约定类 org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention 定义)。类型 long task timer

在启动观测后添加的键值可能会从 *.active 指标中缺失。
Micrometer 内部使用 纳秒 作为基本单位。但是,每个后端确定实际的基本单位。(即 Prometheus 使用秒)

包含类 org.springframework.cloud.config.server.environment.DocumentedConfigObservation 的完全限定名。

所有标签必须以 spring.cloud.config.environment 前缀开头!
表 1. 低基数键

名称

描述

spring.cloud.config.environment.application (必填)

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

spring.cloud.config.environment.class (必填)

EnvironmentRepository 的实现。

spring.cloud.config.environment.label (必填)

正在查询属性的标签。

spring.cloud.config.environment.profile (必填)

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

可观测性 - Span

以下是本项目声明的所有 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 前缀开头!
表 2. 标签键

名称

描述

spring.cloud.config.environment.application (必填)

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

spring.cloud.config.environment.class (必填)

EnvironmentRepository 的实现。

spring.cloud.config.environment.label (必填)

正在查询属性的标签。

spring.cloud.config.environment.profile (必填)

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

© . This site is unofficial and not affiliated with VMware.