Spring Cloud Config Client
Spring Boot 应用程序可以立即利用 Spring 配置服务器(或由应用程序开发者提供的其他外部属性源)。它还会自动获取一些与 Environment 变更事件相关的额外有用功能。
Spring Boot 配置数据导入
Spring Boot 2.4 引入了一种通过 spring.config.import 属性导入配置数据的新方式。如今,这是绑定到配置服务器的默认方式。
可选地连接到配置服务器,请在 application.properties 中设置以下内容:
spring.config.import=optional:configserver:
这将连接到配置服务器的默认位置“http://localhost:8888”。移除 optional: 前缀将导致配置客户端在无法连接到配置服务器时失败。要更改配置服务器的位置,可设置 spring.cloud.config.uri 或在 spring.config.import 语句中添加 URL,例如 spring.config.import=optional:configserver:http://myhost:8888。导入属性中的位置优先于 uri 属性。
使用 Spring Boot 配置数据导入方法时,无需 bootstrap 文件(属性文件或 YAML 文件)即可通过 spring.config.import 进行导入。 |
配置首 Bootstrap
要使用传统的 Bootstrap 方式连接到配置服务器,必须通过属性或 spring-cloud-starter-bootstrap Starters启用 Bootstrap。该属性为 spring.cloud.bootstrap.enabled=true。它必须设置为系统属性或环境变量。
一旦启用了 Bootstrap,任何类路径中包含 Spring Cloud Config Client 的应用程序都将按照如下方式连接到配置服务器:
当配置客户端启动时,它会通过 spring.cloud.config.uri 的 Bootstrap 配置属性绑定到配置服务器,并使用远程属性源初始化 Spring Environment。
这种行为的最终结果是,所有希望使用配置服务器的客户端应用程序都需要在 bootstrap.yml(或环境变量)中设置服务器地址 spring.cloud.config.uri(默认值为 "http://localhost:8888")。
发现首次查找
除非您正在使用 配置优先引导,否则您需要在配置属性中包含一个 spring.config.import 属性,并带有 optional: 前缀。例如,spring.config.import=optional:configserver:。 |
如果您使用 DiscoveryClient 实现方式,例如 Spring Cloud Netflix 和 Eureka 服务发现或 Spring Cloud Consul,您可以使配置服务器注册到发现服务中。
如果您更倾向于使用 DiscoveryClient 来定位配置服务器,可以通过设置 spring.cloud.config.discovery.enabled=true 实现(默认值为 false)。
例如,在 Spring Cloud Netflix 中,您需要定义 Eureka 服务器地址(例如,在 eureka.client.serviceUrl.defaultZone 中进行配置)。
使用此选项的代价是在启动时多一次网络往返,用于定位服务注册信息。
其优势在于:只要发现服务(Discovery Service)是固定点,配置服务器就可以更改其位置坐标。
默认服务 ID 是 configserver,但您可以在客户端通过设置 spring.cloud.config.discovery.serviceId 进行修改(在服务端,则可通过常规的服务配置方式,如设置 spring.application.name 来实现)。
发现客户端实现均支持某种元数据映射(例如,我们有 eureka.instance.metadataMap 用于 Eureka)。
一些额外的配置服务器属性可能需要在服务注册元数据中进行配置,以便客户端能够正确连接。
如果配置服务器使用 HTTP 基本认证进行保护,您可以将凭据配置为 user 和 password。
此外,如果配置服务器具有上下文路径,您可以设置 configPath。
例如,以下 YAML 文件是用于一个作为 Eureka 客户端的配置服务器:
eureka:
instance:
...
metadataMap:
user: osufhalskjrtl
password: lviuhlszvaorhvlo5847
configPath: /config
发现第一个使用 Eureka 和 WebClient 的 Bootstrap
如果您使用 Spring Cloud Netflix 的 Eureka DiscoveryClient,并且也希望使用 WebClient 而非 Jersey 或 RestTemplate,则还需要将 WebClient 添加到您的类路径(classpath)中,并设置 eureka.client.webclient.enabled=true。
配置客户端快速失败
在某些情况下,您可能希望如果服务无法连接到配置服务器,则中止服务的启动。如果这是所需的行为,请将引导配置属性 spring.cloud.config.fail-fast=true 设置为使客户端抛出异常并停止运行。
要使用 spring.config.import 实现类似的功能,只需省略 optional: 前缀即可。 |
配置客户端重试
如果您预期配置服务器在应用程序启动时可能偶尔不可用,您可以使其在失败后继续重试。
首先,您需要设置 spring.cloud.config.fail-fast=true。
然后,您需要将 spring-retry 和 spring-boot-starter-aop 添加到您的类路径中。
默认行为是在初始退避间隔为 1000 毫秒、后续退避采用 1.1 的指数乘数下,重试六次。
您可以通过设置 spring.cloud.config.retry.* 配置属性来配置这些属性(以及其他属性)。
要完全控制重试行为且正在使用传统的引导(bootstrap)方式,请添加一个类型为 RetryOperationsInterceptor、ID 为 configServerRetryInterceptor 的 @Bean。Spring Retry 提供了一个 RetryInterceptorBuilder,支持创建一个。 |
配置客户端重试与 spring.config.import
重试功能与 Spring Boot spring.config.import 语句以及常规属性一起使用。然而,如果导入语句位于某个配置文件中(例如 application-prod.properties),则需要采用不同的方式来配置重试。配置信息必须作为 URL 参数添加到导入语句中。
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.* 来重写所有这些选项(其中 * 是 name、profile 或 label)。label 对于回滚到先前的配置版本非常有用。在默认的配置服务器实现中,它可以是一个 Git 标签、分支名称或提交 ID。标签也可以以逗号分隔的列表形式提供。在这种情况下,会按顺序逐一尝试列表中的各项,直到某一项成功为止。这种行为在开发功能分支时非常有用。例如,您可能希望将配置标签与您的分支对齐,但又使其可选(此时可使用 spring.cloud.config.label=myfeature,develop)。
为配置服务器指定多个URL
为了确保在部署了多个 Config Server 实例且预期其中一或多个实例会不时不可用的情况下仍能保持高可用性,您可以选择以下任一方式:要么在 spring.cloud.config.uri 属性下指定多个 URL(以逗号分隔的列表形式),要么让所有实例在服务注册中心(如 Eureka)中进行注册(如果使用的是发现优先引导模式)。需要注意的是,上述方法仅在 Config Server 未运行(即应用程序已退出)或发生连接超时的情况下才能确保高可用性。例如,若 Config Server 返回 500(内部服务器错误)响应,或 Config 客户端从 Config Server 收到 401 响应(因凭证错误或其他原因),则 Config 客户端将不会尝试从其他 URL 获取配置属性。此类错误通常表明是用户操作问题,而非可用性问题。
如果您在配置服务器上使用 HTTP 基本安全机制,则目前仅当您将凭据嵌入到 spring.cloud.config.uri 属性下所指定的每个 URL 中时,才支持针对每个配置服务器的独立认证凭据。如果您使用其他任何种类的安全机制,则目前无法支持针对每个配置服务器的身份验证和授权。
配置超时设置
如果您希望配置超时阈值:
-
读取超时可以通过使用属性
spring.cloud.config.request-read-timeout进行配置。 -
连接超时可以通过使用属性
spring.cloud.config.request-connect-timeout进行配置。
安全
如果服务器上使用 HTTP 基本认证,则客户端需要知道密码(如果用户名不是默认值,还需知道用户名)。<br/>您可以通过配置服务器的 URI 或通过独立的用户名和密码属性来指定用户名和密码,如下例所示:
spring:
cloud:
config:
uri: https://user:[email protected]
以下示例展示了另一种传递相同信息的方式:
spring:
cloud:
config:
uri: https://myconfig.mycompany.com
username: user
password: secret
The spring.cloud.config.password and spring.cloud.config.username values override anything that is provided in the 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-type 和 spring.cloud.config.tls.trust-store-type 的值为 PKCS12。当密码属性被省略时,默认假设为空密码。
如果您使用其他形式的安全机制,可能需要 为 RestTemplate 提供一个 ConfigServicePropertySourceLocator(例如,通过在引导上下文中获取它并注入)。
健康指标
配置客户端提供了一个 Spring Boot 健康指标,该指标尝试从配置服务器加载配置。
可以通过设置 health.config.enabled=false 来禁用该健康指标。
出于性能考虑,响应也会被缓存。
默认的缓存生存时间(TTL)为 5 分钟。
若要更改此值,请设置 health.config.time-to-live 属性(单位:毫秒)。
提供自定义 RestTemplate
在某些情况下,您可能需要自定义客户端向配置服务器发出的请求。通常,这样做的方式是传递特殊的 Authorization 头部以对服务器请求进行身份验证。要提供一个自定义的 RestTemplate:
-
创建一个新的配置bean,其包含
PropertySourceLocator的实现,如以下示例所示:
@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.* 属性来替代。 |
-
在
resources/META-INF中,创建一个名为spring.factories的文件,并指定您的自定义配置,如下所示示例:
org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration
Vault
当使用 Vault 作为配置服务器的后端时,客户端需要提供一个Tokens,以便服务器从 Vault 中检索值。此Tokens可通过在客户端设置 spring.cloud.config.token 在 bootstrap.yml 中提供,如下例所示:
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。