Skip to content

分布式配置中心

分布式配置中心是微服务架构中的核心组件,用于集中管理各个环境中的应用配置,实现配置的动态更新。Spring Cloud Config 提供了配置服务器和客户端支持,简化了分布式系统中的配置管理。

为什么需要分布式配置中心?

在微服务架构中,配置管理面临以下挑战:

  1. 服务数量多:随着服务数量增加,配置文件管理变得困难
  2. 配置环境多:开发、测试、生产等多环境配置需要管理
  3. 配置变更频繁:频繁的配置变更需要有效的版本控制和回滚机制
  4. 配置实时生效:配置变更后需要实时通知各个服务实例
  5. 配置安全性:敏感配置(如数据库密码)需要加密处理

分布式配置中心解决了这些问题,它提供:

  • 配置的集中管理
  • 配置的环境隔离
  • 配置的版本控制
  • 配置的动态刷新
  • 配置的安全存储

Spring Cloud Config

Spring Cloud Config 是 Spring Cloud 提供的配置管理解决方案,它包含服务端(Config Server)和客户端(Config Client)两部分。

Spring Cloud Config Server

Config Server 是一个独立的微服务应用,它连接到配置仓库(如 Git 仓库)并为客户端提供配置信息。

配置服务器搭建

  1. 添加依赖
xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
  1. 启用配置服务器
java
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
  1. 配置文件(application.yml)
yaml
server:
  port: 8888

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-username/your-config-repo
          search-paths: '{application}'
          default-label: main
          # 如果是私有仓库
          username: your-username
          password: your-password

在上述配置中:

  • uri: Git 仓库地址
  • search-paths: 搜索配置文件的路径模式,{application} 会被替换为客户端的应用名称
  • default-label: Git 仓库的默认分支

配置文件命名规则

Spring Cloud Config 支持以下命名规则的配置文件:

  1. {application}-{profile}.yml.properties
  2. {application}.yml.properties
  3. application-{profile}.yml.properties
  4. application.yml.properties

其中:

  • {application}: 应用名称
  • {profile}: 环境标识,如 dev, test, prod

优先级从高到低,如 service-a-dev.yml 的优先级高于 service-a.yml

配置服务器 REST API

配置服务器暴露了以下 REST API:

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

例如:

  • http://config-server:8888/service-a/dev: 获取 service-a 应用的 dev 环境配置
  • http://config-server:8888/service-a-dev.yml: 以 YAML 格式获取配置

Spring Cloud Config Client

Config Client 是微服务应用,它在启动时连接到 Config Server 获取配置信息。

客户端配置

  1. 添加依赖
xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
  1. 创建 bootstrap.yml(或 bootstrap.properties)
yaml
spring:
  application:
    name: service-a
  profiles:
    active: dev
  cloud:
    config:
      uri: http://config-server:8888
      fail-fast: true  # 连接配置中心失败时快速失败

注意:从 Spring Cloud 2020.0.0 版本开始,bootstrap 默认被禁用。如果使用的是这个版本或更高版本,需要添加 spring-cloud-starter-bootstrap 依赖,或在 application.yml 中使用新的配置方式。

对于 Spring Cloud 2020.0.0 及以上版本,可以使用以下配置:

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

或者,在 application.yml 中配置:

yaml
spring:
  config:
    import: optional:configserver:http://config-server:8888
  application:
    name: service-a
  profiles:
    active: dev
  1. 使用配置

客户端应用可以通过 @Value 注解、Environment 或者 @ConfigurationProperties 访问配置:

java
@RestController
@RefreshScope  // 允许配置动态刷新
public class ConfigController {

    @Value("${app.message}")
    private String message;
    
    @GetMapping("/message")
    public String getMessage() {
        return message;
    }
}

配置动态刷新

当配置在配置服务器中更新后,客户端需要刷新才能获取新值。Spring Cloud Config 提供了多种配置刷新方式。

手动刷新

  1. 添加 Actuator 依赖
xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. 配置 Actuator 端点
yaml
management:
  endpoints:
    web:
      exposure:
        include: refresh
  1. 使用 @RefreshScope 注解标记需要动态刷新的 Bean
java
@RefreshScope
@Component
public class ConfigProperties {
    @Value("${app.message}")
    private String message;
    
    // getter and setter
}
  1. 手动调用刷新端点

当配置变更后,调用 /actuator/refresh 端点触发配置刷新:

bash
curl -X POST http://service-a:8080/actuator/refresh

使用 Spring Cloud Bus 实现自动刷新

手动刷新在服务实例多的情况下不实用,Spring Cloud Bus 可以实现配置的批量刷新。

  1. 添加依赖
xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

或者使用 Kafka:

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
  1. 配置消息中间件连接

以 RabbitMQ 为例:

yaml
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
  1. 配置 Actuator 端点
yaml
management:
  endpoints:
    web:
      exposure:
        include: refresh,bus-refresh
  1. 调用总线刷新端点

当配置变更后,只需调用任一服务实例的 /actuator/bus-refresh 端点,所有连接到同一消息总线的服务实例都会刷新配置:

bash
curl -X POST http://service-a:8080/actuator/bus-refresh

使用 Webhooks 实现自动刷新

更进一步,可以使用 Git 仓库的 Webhooks 触发配置自动刷新。这样当配置仓库发生变更时,会自动通知配置中心,进而通知各个服务更新配置。

  1. 配置 Config Server 暴露 /monitor 端点
yaml
management:
  endpoints:
    web:
      exposure:
        include: monitor
  1. 在 Git 仓库(如 GitHub)配置 Webhooks,URL 指向 http://config-server:8888/monitor,内容类型设置为 application/json

高级特性

配置加密与解密

Spring Cloud Config 支持配置值加密,保护敏感信息:

  1. 配置加密密钥(对称加密)
yaml
encrypt:
  key: some-secret-key

或者使用非对称加密:

yaml
encrypt:
  key-store:
    location: classpath:keystore.jks
    password: ${KEYSTORE_PASSWORD}
    alias: config-server-key
    secret: ${KEY_PASSWORD}
  1. 加密配置值
bash
curl -X POST http://config-server:8888/encrypt -d mypassword

这会返回加密后的值,如:AQAkGVlRz7YB0Td8zs+UZfm1eX8/t26K7xLTvzWV/Knm4qwYxiWbX8jQs2b/

  1. 在配置文件中使用加密值
yaml
spring:
  datasource:
    password: '{cipher}AQAkGVlRz7YB0Td8zs+UZfm1eX8/t26K7xLTvzWV/Knm4qwYxiWbX8jQs2b/'

客户端会自动解密使用 {cipher} 前缀的值。

配置的健康检查

Config Client 可以配置健康检查,确保与配置服务器的连接正常:

yaml
spring:
  cloud:
    config:
      fail-fast: true  # 连接配置中心失败时快速失败
      retry:           # 重试配置
        initial-interval: 1000
        max-attempts: 6
        max-interval: 2000
        multiplier: 1.1

配置属性重载顺序

Spring Cloud Config 有明确的属性加载优先级:

  1. 远程仓库(如 Git)的 application.yml 和其他配置文件
  2. 本地配置文件 bootstrap.yml
  3. 本地配置文件 application.yml

指定配置文件占位符

可以在客户端使用占位符从本地配置文件中获取配置:

yaml
spring:
  cloud:
    config:
      uri: http://config-server:${config.port:8888}

备份配置

为保证配置中心不可用时应用仍能正常启动,可以采用备份配置:

  1. 使用配置客户端启动器的重试机制
  2. 在客户端本地保留最近一次成功的配置备份
  3. 使用本地文件系统作为备份的配置源

Spring Cloud Config 与服务发现集成

Config Server 可以注册到服务发现系统,客户端通过服务发现找到 Config Server:

  1. 在 Config Server 中添加服务发现依赖,如 Eureka Client:
xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 启用服务发现
java
@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
  1. 客户端配置使用服务发现查找 Config Server
yaml
spring:
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-server

使用文件系统作为配置源

除了 Git 仓库,Spring Cloud Config 也支持使用本地文件系统作为配置源:

yaml
spring:
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations: file:/config-repo

注意:使用 native 配置文件激活本地文件系统模式。

使用 Spring Cloud Config 的最佳实践

  1. 配置分层管理:将配置分为应用级、环境级和默认三层,利用继承关系减少重复配置
  2. 敏感配置加密:对数据库密码等敏感信息进行加密
  3. 版本控制:使用 Git 的版本控制能力,方便配置回滚
  4. 高可用配置中心:部署多个 Config Server 实例,避免单点故障
  5. 配置变更审计:利用 Git 的提交历史进行配置变更审计
  6. 环境隔离:使用不同分支或仓库严格隔离各环境配置
  7. 结合服务发现:Config Server 注册到服务注册中心,简化客户端配置
  8. 自动化刷新:使用 Spring Cloud Bus 实现配置的自动刷新
  9. 健康检查:启用健康检查,及时发现配置中心问题
  10. 合理的配置粒度:配置不要过粗或过细,保持合理的粒度

替代方案比较

除了 Spring Cloud Config,还有其他常用的分布式配置中心:

特性Spring Cloud ConfigNacosApolloConsul
开发语言JavaJavaJavaGo
配置存储Git/文件系统内存/MySQLMySQL内存/文件系统
配置格式YAML/PropertiesYAML/Properties/JSONPropertiesKV
配置推送拉取为主,结合消息总线推送实时推送实时推送实时推送
权限控制基本支持细粒度支持细粒度支持基本支持
版本控制依赖 Git内置内置有限支持
配置审计依赖 Git内置内置有限支持
配置回滚依赖 Git支持支持有限支持
多环境支持支持支持有限支持
可视化控制台无(需自行开发)
Spring Cloud 集成原生支持通过 Spring Cloud Alibaba通过适配器通过 Spring Cloud Consul

总结

Spring Cloud Config 提供了一套完整的分布式配置管理解决方案,满足了微服务架构下配置集中管理的需求。它具有以下特点:

  1. 支持配置的集中管理和版本控制
  2. 提供配置的加密和解密功能
  3. 与 Spring Boot 生态系统无缝集成
  4. 支持配置的动态刷新,特别是与 Spring Cloud Bus 结合
  5. 提供多种配置存储方式,如 Git、文件系统等

在选择分布式配置中心时,应根据团队技术栈、功能需求和运维能力综合考虑。Spring Cloud Config 作为 Spring Cloud 生态的一部分,对于 Spring Boot 应用来说是一个很好的选择,尤其是当团队已经在使用 Git 进行配置管理时。