Skip to content

Config 详解:不止是配置中心

  Spring Cloud Config 是 Spring Cloud 官方提供的配置管理组件。但它不只是"配置中心"——它是一套完整的配置治理方案,涵盖了配置的存储、版本管理、动态刷新、加密保护、广播通知等多个能力。

一、Config 不只是配置中心

  很多人把 Config 简单理解成"把配置文件从本地搬到 Git 仓库",但这个理解过于片面。Config 实际提供的是一套完整的配置治理能力:

                    ┌─────────────────────────────────────────────┐
                    │          Spring Cloud Config                 │
                    │                                             │
                    │  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
                    │  │ 集中管理  │  │ 动态刷新  │  │ 版本管理  │  │
                    │  │ 统一存储  │  │ 不重启生效│  │ Git 追溯  │  │
                    │  └──────────┘  └──────────┘  └──────────┘  │
                    │                                             │
                    │  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
                    │  │ 环境隔离  │  │ 加密保护  │  │ 广播通知  │  │
                    │  │ dev/test/ │  │ 敏感信息  │  │ 一键刷新  │  │
                    │  │ prod     │  │ 密文存储  │  │ 全集群    │  │
                    │  └──────────┘  └──────────┘  └──────────┘  │
                    │                                             │
                    │  ┌──────────┐  ┌──────────┐                │
                    │  │ 高可用   │  │ 灰度发布  │                │
                    │  │ 启动快失败│  │ 按标签推送│                │
                    │  │ 自动重试  │  │ 配置      │                │
                    │  └──────────┘  └──────────┘                │
                    └─────────────────────────────────────────────┘
能力说明实现方式
集中管理所有服务的配置统一存储在 Git/SVN/NativeConfig Server 拉取配置源
动态刷新修改配置后不用重启服务即可生效@RefreshScope + POST /actuator/refresh
版本管理配置变更历史可追溯、可回滚Git 天然版本控制,查看 commit log
环境隔离dev/test/prod 配置隔离,互不影响文件名规则:{application}-{profile}.yml
加密保护数据库密码等敏感信息密文存储{cipher} 前缀 + 对称/非对称加密
广播通知一次刷新,所有实例同时生效Config + Bus + MQ 广播
高可用配置中心不可用时服务能启动fail-fast + retry 机制
灰度发布配置按标签推送给指定实例4.0+ 支持 spring.cloud.config.label

一句话:Config 解决的是"配置的治理问题",而不仅仅是"配置的存储问题"。

二、为什么需要配置中心?

2.1 没有配置中心时的痛点

application.yml 散落在每个服务里:
  order-service/application.yml     → 数据库连接、限流阈值、开关配置
  user-service/application.yml      → 数据库连接、Redis 地址、开关配置
  inventory-service/application.yml → 数据库连接、MQ 地址、开关配置

问题:
  1. 配置分散:修改一个配置要改 N 个服务,且需要重新部署
  2. 环境混乱:dev/test/prod 配置混在一起,容易出错
  3. 无法追溯:谁改了什么配置?什么时间改的?没有记录
  4. 安全风险:敏感信息(密码/密钥)明文存储在代码仓库

2.2 有了配置中心之后

┌──────────────────────────────────────────────────────────────────┐
│                     Spring Cloud Config Server                    │
│                                                                  │
│  Git 仓库 / 本地文件系统(配置源)                                  │
│  ├── application.yml          ← 公共配置                          │
│  ├── order-service.yml        ← 订单服务配置                       │
│  ├── order-service-dev.yml    ← 订单服务开发环境                   │
│  └── order-service-prod.yml   ← 订单服务生产环境                   │
│                                                                  │
│  所有服务启动时向 Config Server 拉取配置,统一管理                  │
└──────────────────────────────────────────────────────────────────┘
        ↑               ↑               ↑
   order-service   user-service   inventory-service

三、核心架构

┌──────────────────────────────────────────────────────────────────┐
│                        Config 架构图                              │
│                                                                  │
│  ┌──────────────┐                                                │
│  │  Git 仓库     │ ← 配置文件存储(或 SVN、本地文件、Vault)        │
│  │  (配置源)     │                                                │
│  └──────┬───────┘                                                │
│         │ 拉取配置                                                │
│         ▼                                                        │
│  ┌──────────────────┐                                            │
│  │  Config Server    │ ← 配置服务端,提供 REST API                 │
│  │  (配置中心服务)    │    端点:/{application}/{profile}[/{label}] │
│  └────────┬─────────┘                                            │
│           │ 提供配置                                               │
│           ▼                                                      │
│  ┌──────────────────┐     ┌──────────────────┐                   │
│  │  Config Client    │     │  Config Client    │                   │
│  │  (order-service)  │     │  (user-service)   │                   │
│  │                   │     │                   │                   │
│  │  启动时拉取配置    │     │  启动时拉取配置    │                   │
│  │  /actuator/refresh│     │  /actuator/refresh│                   │
│  └──────────────────┘     └──────────────────┘                   │
│                                                                  │
│  配置刷新流程:                                                    │
│  Git 变更 → Config Server → Bus 广播 → Client refresh             │
└──────────────────────────────────────────────────────────────────┘

四、Config Server 服务端

4.1 依赖

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

4.2 启动类

java
@SpringBootApplication
@EnableConfigServer  // 开启配置中心
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

4.3 配置(Git 后端,推荐)

yaml
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/team/config-repo    # Git 仓库地址
          search-paths: config                         # 搜索路径
          default-label: main                          # 默认分支
          username: your-username                      # 私有仓库需要
          password: your-password
          # 本地缓存(避免 Git 不可用时服务无法启动)
          basedir: /tmp/config-repo
          clone-on-start: true                         # 启动时 clone
          force-pull: true                             # 强制拉取最新
          refresh-rate: 30                             # 刷新间隔(秒)

server:
  port: 8888

4.4 配置(Native 本地文件,适合简单场景)

yaml
spring:
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations: file:///D:/config-repo    # 本地文件路径

4.5 访问规则

Config Server 提供 REST API 来获取配置,URL 格式为:

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

示例:
  http://localhost:8888/order-service/dev          → 返回 order-service-dev.yml
  http://localhost:8888/order-service/dev/main     → 返回 main 分支的配置
  http://localhost:8888/order-service-prod.yml     → 返回 order-service-prod.yml

五、Config Client 客户端

5.1 依赖

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

5.2 配置(bootstrap.yml)

yaml
# bootstrap.yml 优先级高于 application.yml,用于引导配置
spring:
  application:
    name: order-service
  cloud:
    config:
      uri: http://localhost:8888          # Config Server 地址
      profile: dev                         # 环境
      label: main                          # 分支
      fail-fast: true                      # 连接失败时快速失败
      retry:
        initial-interval: 1000             # 重试间隔
        max-attempts: 6                    # 最大重试次数
        multiplier: 1.5                    # 间隔倍数

# 暴露 refresh 端点
management:
  endpoints:
    web:
      exposure:
        include: refresh

5.3 配置热刷新

java
@RestController
@RefreshScope  // 标记为可刷新,配置变更时重新初始化 Bean
public class OrderController {

    @Value("${order.limit:100}")
    private int limit;

    @GetMapping("/limit")
    public String getLimit() {
        return "当前限流阈值:" + limit;
    }
}

刷新方式:

bash
# 方式一:手动调用(单服务)
curl -X POST http://localhost:8080/actuator/refresh

# 方式二:Bus 批量刷新(推荐,见 Bus 章节)
curl -X POST http://config-server:8888/actuator/busrefresh

六、配置优先级

Spring Cloud Config 配置加载顺序(优先级从高到低):

1. 命令行参数                   --spring.profiles.active=prod
2. 系统环境变量                 JAVA_HOME
3. application-{profile}.yml   远程仓库(Config Server)
4. application.yml              远程仓库(Config Server)
5. application-{profile}.yml   本地(classpath)
6. application.yml              本地(classpath)
7. @PropertySource              注解引入

远程配置优先级高于本地配置,这是 Config 的默认行为。可通过 spring.cloud.config.override-none=true 修改。

七、配置加密

yaml
# Config Server 端配置加密密钥
encrypt:
  key: my-secret-key

# 加密配置值
# POST http://localhost:8888/encrypt  Body: mypassword
# 返回: {cipher}xxxxx

# 在配置文件中使用加密值
spring:
  datasource:
    password: '{cipher}xxxxx'  # Config Server 自动解密

八、Config vs Nacos:不是简单的对等关系

8.1 Config 是对标 Nacos 吗?

  不完全对等。 Nacos 在功能上是 Config 的"超集":

┌─────────────────────────────────────────────────────────────────┐
│                      Nacos 是什么?                              │
│                                                                 │
│  ┌──────────────────────┐  ┌──────────────────────┐             │
│  │   服务注册与发现       │  │   配置管理             │             │
│  │   (对等 Eureka/Consul) │  │   (对等 Config)        │             │
│  │                      │  │                      │             │
│  │  - 服务注册           │  │  - 配置存储           │             │
│  │  - 健康检查           │  │  - 动态刷新(自动推送) │             │
│  │  - 元数据管理         │  │  - 历史版本           │             │
│  │  - 权重路由           │  │  - 灰度发布           │             │
│  │  - 保护阈值           │  │  - 命名空间/分组       │             │
│  └──────────────────────┘  └──────────────────────┘             │
│                                                                 │
│  Nacos = 服务发现(Eureka) + 配置中心(Config) + Web 控制台        │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│              Spring Cloud Config 是什么?                        │
│                                                                 │
│  ┌──────────────────────┐                                       │
│  │   配置管理             │                                       │
│  │   (只管配置)          │                                       │
│  │                      │                                       │
│  │  - 配置存储(Git)      │                                       │
│  │  - 动态刷新(手动/Bus) │                                       │
│  │  - 版本管理(Git)      │                                       │
│  │  - 加密保护           │                                       │
│  └──────────────────────┘                                       │
│                                                                 │
│  Config = 只做配置管理,服务发现需要 Eureka/Consul 配合            │
└─────────────────────────────────────────────────────────────────┘

结论:Nacos 相当于 Config + Eureka 二合一,还带 Web 控制台。Config 只做配置管理,服务发现需要另外的组件。

8.2 详细对比

维度Spring Cloud ConfigNacos
定位纯配置管理服务发现 + 配置管理
配置存储Git / SVN / 本地文件内置存储(MySQL / Derby)
配置刷新手动 POST /actuator/refresh + Bus 广播自动推送,秒级生效
服务发现无,需配合 Eureka、Consul、Zookeeper内置,无需额外组件
Web 控制台有,可视化管理
版本管理依赖 Git 的 commit 历史内置历史版本,控制台直接查看
灰度发布通过 Git 分支间接实现内置,按标签/IP 灰度
命名空间无,通过 profile 区分环境内置 namespace,多环境隔离
分组内置 group,按业务分组
加密内置对称/非对称加密不内置,需应用层自行加密
高可用Config Server 集群 + Git 高可用Nacos 集群(内置 Raft 协议)
运维成本需要维护 Git 仓库 + Config Server + Bus(MQ)只维护 Nacos 集群
学习成本中(需理解 Git + Bus 联动)低(开箱即用)
生态归属Spring Cloud 官方Spring Cloud Alibaba

8.3 核心差异:配置刷新方式

这是两者最大的体验差异:

Config 刷新方式(手动):
  开发者修改 Git 配置 → git push
    → POST /actuator/busrefresh(手动触发)
    → Bus 通过 MQ 广播给所有实例
    → 各实例重新加载配置

Nacos 刷新方式(自动):
  开发者在 Nacos 控制台修改配置 → 点击发布
    → Nacos 自动推送通知给所有订阅的实例
    → 各实例 @RefreshScope 的 Bean 自动刷新

Config 是"拉"模式(需手动触发),Nacos 是"推"模式(自动推送)。 这是 Nacos 作为配置中心最大的体验优势。

8.4 两者能一起使用吗?

可以,但通常没必要。 同时使用 Config 和 Nacos 来管理配置属于"重复造轮子"。

同时使用 Config + Nacos 的问题:

  优先级冲突:同一个配置项,Config 和 Nacos 谁说了算?
  维护成本:两个地方管理配置,改一个配置要确认两边是否一致
  排查困难:配置出问题时,不知道是哪个源头的问题
  架构冗余:引入了不必要的复杂度

唯一的例外场景: 配置加密需求

Config 内置加密/解密能力({cipher} 前缀),Nacos 没有。
如果你的配置中有大量敏感信息需要加密,可以:

  ┌──────────────┐      ┌──────────────┐
  │   Nacos      │      │  Config      │
  │  普通配置     │      │ 加密配置      │
  │  (开关/阈值)  │      │ (密码/密钥)   │
  └──────────────┘      └──────────────┘

但更好的做法是:用 Vault 管理敏感配置,Nacos 管理普通配置。
或者直接用 Nacos + 应用层自行加密(如 Jasypt)。

8.5 用了 Nacos 还有必要用 Config 吗?

绝大多数场景:不需要。

场景还需要 Config 吗?原因
用了 Nacos 做注册+配置❌ 不需要Nacos 已经覆盖了 Config 的全部功能
需要配置加密⚠️ 可选Config 有内置加密,但 Jasypt/Vault 更合适
需要 Git 审计追溯⚠️ 可选Nacos 有历史版本,但 Git 审计更强
已有 Git 运维体系⚠️ 可选如果团队极度依赖 Git 做 change review
用了 Eureka 做注册✅ 需要用 Config 做配置管理是标准组合
混用两套体系❌ 不建议架构复杂度增加,维护成本翻倍

标准组合推荐:

方案 A:Spring Cloud 原生方案
  ┌──────────┐  ┌──────────┐  ┌──────────┐
  │  Eureka  │  │  Config  │  │   Bus    │
  │ 服务发现  │  │ 配置管理  │  │ 配置广播  │
  └──────────┘  └──────────┘  └──────────┘

方案 B:Spring Cloud Alibaba 方案(推荐)
  ┌──────────────────────┐
  │        Nacos         │
  │  服务发现 + 配置管理   │
  └──────────────────────┘
  一个组件搞定两个功能,运维成本最低

方案 C:自建 + Nacos 混合(不推荐)
  ┌──────────┐  ┌──────────┐
  │  Config  │  │  Nacos   │
  │ 配置管理?│  │ 配置管理?│  ← 两个配置中心,冲突
  └──────────┘  └──────────┘

方案 D:Nacos + Vault(加密场景)
  ┌──────────┐  ┌──────────┐
  │  Nacos   │  │  Vault   │
  │ 普通配置  │  │ 敏感配置  │  ← 职责清晰,不冲突
  └──────────┘  └──────────┘

一句话:Nacos 已经包含了 Config 的能力,两者选一个即可。除非你有 Git 审计或加密的特殊需求,否则不需要同时使用。

九、面试要点

Q1:Config 配置刷新的原理?

  调用 /actuator/refresh 时,@RefreshScope 标注的 Bean 会被重新初始化。底层通过 ContextRefresher.refresh() 重新加载 Environment 中的配置,并销毁重建 RefreshScope 中的 Bean。

Q2:bootstrap.yml 和 application.yml 的区别?

  bootstrap.yml 优先级更高,在应用启动的引导阶段加载,用于获取 Config Server 地址等引导配置。application.yml 在引导完成后加载。Spring Boot 3.x 中 bootstrap 默认不启用,需要引入 spring-cloud-starter-bootstrap

Q3:Config Server 高可用怎么做?

  部署多个 Config Server 实例,前面挂一个 LoadBalancer。客户端通过 spring.cloud.config.uri 配置多个地址,或通过服务发现(Eureka/Nacos)自动发现 Config Server 实例。

Q4:Git 不可用时怎么办?

  Config Server 会使用本地缓存(basedir 指定的目录)。设置 clone-on-start: true 确保启动时已 clone 成功。配合 fail-fast: true 在网络问题时快速感知。