Spring Cloud Config 使用 GIT 以外的配置源

1、简介

Spring Cloud Config 是 Spring Cloud 生态下的一个子项目,可让 Spring 应用轻松实现配置外部化。通过它,可以将配置数据作为服务暴露出来,从而使得任何具有 HTTP 客户端的应用都可以轻松地获取配置数据。

本文将会带你了解如何在 Spring Cloud Config 中使用 Git 以外的配置源来存储配置信息。

2、Spring Cloud Config 概览

Spring Cloud Config 采用了典型的客户端-服务器模型。集中式服务器(或多个服务器)从外部数据源读取配置数据。这些服务器会暴露各种 HTTP 端点,允许任何其他应用查询配置数据。

spring cloud config 概览

Spring Cloud Config 还能让 Spring Boot 应用非常方便地自动连接到配置服务器。服务器提供的配置数据可以像客户端应用中的其他属性源一样使用。

3、GIT

Spring Cloud Config 最常见的使用案例是在 git 仓库中存储配置数据。这种方式的设置有几个优点:

  • 灵活性:git 仓库可以容纳各种类型的文件,包括二进制文件。
  • 安全性:可轻松控制细粒度的读写权限。
  • 审计:强大的历史跟踪功能可轻松审核配置更改。
  • 标准化:无论哪家提供商(Provider),Git 操作都是标准的,这意味着我们可以自行托管或使用任意数量的第三方提供商。
  • 分布式: Git 从一开始就是为分布式设计的,因此非常适合云原生和微服务架构。

尽管有上述种种好处,但 git 并不总是存储配置数据的最佳选择。例如,项目可能已经将配置数据放在其他数据存储(如关系型数据库)中。在这种情况下,将其迁移到 git 可能就得不偿失了。

4、使用 GIT 以外的 配置源

在 Spring Cloud Config 中使用 git 以外的其他配置源时时,指的其实是服务器组件。对数据存储的选择不会影响客户端组件。只有服务器会受到影响。

在 Spring Cloud Config Server 库中,有一个名为 EnvironmentRepository 的接口定义了一个配置源。所有配置源(包括 git 和其他配置源)都必须实现该接口。

让我们来看看所提供的一些实现。

3.1、文件系统

Spring Cloud Config 支持将文件系统用作配置源。要启用此功能,必须在配置服务器的 application.properties 文件中指定以下值:

spring.cloud.config.server.native.search-locations=resources/other.properties

默认情况下,搜索位置假定为 classpath 下的资源。如果我们想使用任意文件,只需包含一个 file 资源前缀即可:

spring.cloud.config.server.native.search-locations=file:///external/path/other.properties

除此属性外,配置服务器还需要启用 native Profile:

-Dspring.profiles.active=native

在使用文件系统配置源时,需要确保文件系统在配置服务器运行的任何地方都是可用的。这可能意味着要使用 NFS 等分布式文件系统。

3.2、JDBC

Spring Cloud Config 也可以使用关系型数据库通过 JDBC 加载配置数据。这是通过 JdbcEnvironmentRepository 类实现的。要启用此类,我们需要按照几个步骤进行操作。

首先,classpath 上必须有 spring-jdbc 库。如果已经在使用 Spring Data JDBC 或其他依赖,那么它就已经存在了。否则,需要手动指定:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
</dependency>

其次,需要指定如何连接数据库:

spring.datasource.url=jdbc:mysql://dbhost:3306/springconfig
spring.datasource.username=dbuser
spring.datasource.password=dbpassword
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

在本例中,使用的是 MySQL,但任何兼容 JDBC 的驱动程序都可以使用。

接下来,数据库必须包含一个名为 PROPERTIES 的表,该表有以下列:

  • APPLICATION
  • PROFILE
  • LABEL
  • KEY
  • VALUE

最后,需要为配置服务器指定 JDBC Profile:

-Dspring.profiles.active=jdbc

3.3、Redis

Spring Cloud Config 还支持将 Redis 作为配置源。这是通过 RedisEnvironmentRepository 类实现的。与 JDBC 源类似,需要遵循几个步骤来启用它。

首先,需要添加 Spring Data Redis 依赖:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>

其次,需要为如何连接 Redis 设置一些属性:

spring.redis.host=localhost
spring.redis.port=6379

接下来,必须确保属性正确存储在 Redis 中。可以使用 HMSET 命令来存储一些示例属性:

HMSET application sample.property.name1 "somevalue" sample.property.name2 "anothervalue"

使用 HGETALL 查看数据:

HGETALL application
{
    "sample.property.name1": "somevalue",
    "sample.property.name2": "anothervalue"
}

最后,必须为 Spring Cloud Config 服务器启用 Redis Profile:

-Dspring.profiles.active=redis

使用 Redis 作为配置源还支持不同的 Profile。为此,只需在 application 末尾添加 Profile 名称即可:

HMSET application-dev sample.property.name1 "somevalue" sample.property.name2 "anothervalue"

如上,在名为 dev 的 Profile 下创建一组新属性。

3.4、Secrets

Secrets 是许多云服务商的常用功能。Secrets 允许我们将敏感数据作为云基础设施的一部分进行安全存储。对于用户名、主机名和密码等我们希望作为应用配置一部分的内容来说,Secrets 是再好不过的了。

Spring Cloud Config 支持许多不同的云 Secret 提供商。下面,我们将介绍 AWS,它使用 AwsSecretsManagerEnvironmentRepository 类将 AWS Secrets 加载到属性源中。

该类依赖 AWSSecretsManager 类来完成与 AWS 通信的繁琐工作。虽然我们可以自己手动创建,但更直接的解决方案是使用 Spring Starter

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-aws-secrets-manager-config</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

该模块包含一个自动配置,可为我们创建一个 AWSSecretsManager 实例。我们只需在 bootstrap.yml 文件中指定一组属性即可:

aws:
  secretsmanager:
    default-context: application
    prefix: /config
    profile-separator: _
    fail-fast: true
    name: ConfigServerApplication
    enabled: true

现在,假设我们想将数据库凭证存储在 secret 中,并将其提供给配置服务器。我们只需在 /config/application/database_credentials 路径下创建一个新的 secret。并在其中存储连接数据库所需的键/值对。

这种结构还支持不同的 Profile。例如,如果我们有一个开发数据库服务器,我们也可以为它创建一个单独的 Secret。可以将其命名为 /config/application/database_credentials_dev

3.5、S3

另一种方便的配置存储方式是使用云文件服务。如 AWS S3。

首先,在项目中添加 AWS SDK

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-s3outposts</artifactId>
    <version>1.12.150</version>
</dependency>

然后,需要提供一些值来配置与包含 property 文件的 S3 bucket 的连接:

amazon.s3.access-key=key
amazon.s3.secret-key=secret

此外,还需要为 AWS S3 Configuration Provider 提供特定属性:

spring:
  cloud:
    config:
      server:
        awss3:
          region: us-east-1
          bucket: config-bucket

还需要设置一个 Profile,以确保加载 AWS S3 配置源:

-Dspring.profiles.active=awss3

剩下的工作就是在 bucket 内创建我们所需的 properties 文件,包括任何特定于 Profile 的文件。注意,当应用没有 Profile 时,配置服务器会假定为 default。因此,应在其他包含特定 Profile 名称的文件中加入一个带有该后缀的文件。

3.6、自定义配置源

如果上述提供的配置源不能满足我们的需求,可以选择实现我们自己的配置源。一般来说,这需要创建一个同时实现 EnvironmentRepositoryOrdered 的新类:

public class CustomConfigurationRepository implements EnvironmentRepository, Ordered {
    @Override
    public Environment findOne(String application, String profile, String label) {
        // 返回一个新 Environment,该 Environment 由所需的数据源(数据库、NoSQL 存储等)填充
    }

    @Override
    public int getOrder() {
        // 定义相对于其他 Configuration Repository
        return 0;
    }
}

然后,只需将该类实例化为一个新的 Spring Bean:

@Bean
public CustomConfigurationRepository customConfigurationRepository() {
    return new CustomConfigurationRepository();
}

4、多配置源

在某些情况下,可能需要使用多个配置源运行 Spring Cloud Config。在这种情况下,必须指定几项数据。

比方说,我们希望同时使用 JDBC 和 Redis 作为配置源。需要做的第一件事就是在 bootstrap.yml 文件中定义每个源的顺序:

spring:
  cloud:
    config:
      server:
        redis:
          order: 2
        jdbc:
          order: 1

这样,就可以指定哪些配置源应优先于其他配置源使用。排序遵循正常的 Spring Ordered 注解处理方式,值较小的配置源将首先被检查。

此外,还需要为服务器定义两个 Profiles:

-Dspring.profiles.active=jdbc,redis

注意,也可以在 YAML 中指定激活的 Profile。同样的模式也可用于定义任意数量的配置源。

5、总结

本文介绍了 Spirng Cloud Config 如何使用除 GIT 以外的配置源,如:文件系统、JDBC(关系型数据库)、Redis、Secrets、S3 和自定义的配置源。


参考:https://www.baeldung.com/spring-cloud-config-without-git