Skip to content
第 225 / 250 章架构⏱ 12 分钟阅读

第 225 章:Spring Cloud Config 与配置中心

学习目标

  • 掌握 Spring Cloud Config
  • 学会使用 Nacos Config
  • 实现配置的动态刷新
  • 配置加解密

一、配置中心定位

1.1 为什么需要配置中心

痛点配置中心解决
配置散落各服务集中管理
改配置需重启动态刷新
多环境不一致环境隔离
密钥明文存储加密存储
修改无审计版本追踪

1.2 对比

产品后端存储动态刷新易用度
Spring Cloud ConfigGit需 Bus简单
Nacos ConfigMySQL自动⭐⭐⭐⭐
ApolloMySQL自动 + Web⭐⭐⭐⭐⭐
Consul KVRaftwatch

二、Spring Cloud Config

2.1 服务端

依赖:

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

配置:

yaml
server:
  port: 8888

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/myorg/config-repo
          username: ${git-user}
          password: ${git-pass}
          default-label: main
          search-paths: '{application}'

启动类:

java
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication { ... }

2.2 客户端

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

bootstrap.yml:

yaml
spring:
  application:
    name: order-service
  cloud:
    config:
      uri: http://localhost:8888
      profile: dev
      label: main

2.3 客户端配置加载顺序

三、Nacos Config(推荐)

3.1 引入

xml
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

3.2 bootstrap.yml

yaml
spring:
  application:
    name: order-service
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        namespace: prod
        group: DEFAULT_GROUP
        file-extension: yaml
        refresh-enabled: true

        # 拓展配置(优先级高于主配置)
        extension-configs:
          - data-id: order-datasource.yaml
            refresh: true

        # 共享配置
        shared-configs:
          - data-id: common.yaml
            refresh: true
          - data-id: redis.yaml
            refresh: true

3.3 DataId 规则

${spring.application.name}-${spring.profiles.active}.${file-extension}

order-service-dev.yaml

# 还可以有:
order-service.yaml                     # 默认
order-service-prod.yaml                # 生产环境

3.4 配置内容

Nacos 控制台 配置管理 → 配置列表:

yaml
# order-service-dev.yaml
server:
  port: 8081

spring:
  datasource:
    url: jdbc:mysql://dev-mysql:3306/order
    username: dev
    password: dev

order:
  timeout: 3000
  maxRetry: 2
  feature:
    recommendEnabled: true

3.5 配置加载优先级

数值越小优先级越高

四、动态刷新

4.1 单 Bean 刷新

java
@RestController
@RefreshScope   // 关键注解
public class OrderController {

    @Value("${order.timeout}")
    private int timeout;

    @GetMapping("/config")
    public String config() {
        return "timeout=" + timeout;
    }
}

改 Nacos 配置后,30 秒内 Bean 重新创建,生效。

4.2 批量 Bean 刷新

java
@Configuration
@RefreshScope
public class OrderConfig {

    @Bean
    @RefreshScope
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder
            .setConnectTimeout(Duration.ofMillis(timeout))
            .setReadTimeout(Duration.ofMillis(timeout))
            .build();
    }
}

4.3 自定义刷新逻辑

java
@Component
@Slf4j
public class ConfigChangeListener implements ApplicationRunner {

    @Autowired
    private Environment env;

    @Override
    public void run(ApplicationArguments args) {
        NacosFactory.createConfigService("127.0.0.1:8848")
            .addListener("order-service.yaml", "DEFAULT_GROUP", new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("配置变化: {}", configInfo);
                    // 重新读取
                    String timeout = env.getProperty("order.timeout");
                    // 执行自定义逻辑
                    cacheService.refreshAll();
                }
            });
    }
}

五、配置加密

5.1 Jasypt(对称加密)

xml
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.4</version>
</dependency>
yaml
jasypt:
  encryptor:
    password: ${JASYPT_PASSWORD}
java
// 启动类
@SpringBootApplication
@EnableEncryptableProperties
public class Application { ... }

// 测试加密
@Autowired
private StringEncryptor encryptor;

public void test() {
    String enc = encryptor.encrypt("mySecretPass");
    System.out.println(enc);  // ENC(R6b...)
}
yaml
# Nacos 中配置
spring:
  datasource:
    password: ENC(R6bV1O5...)   # 加密值

# 环境变量传入密钥
JASYPT_PASSWORD=my-master-pass

5.2 自定义加密

java
@Bean
public StringEncryptor stringEncryptor() {
    PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
    SimpleStringPBEConfig config = new SimpleStringPBEConfig();
    config.setPassword("my-master-pass");
    config.setAlgorithm("PBEWithMD5AndDES");
    config.setKeyObtentionIterations("1000");
    config.setPoolSize("1");
    encryptor.setConfig(config);
    return encryptor;
}

5.3 加密方案选型

方案特点
Jasypt简单,对称加密
VaultHashiCorp,生产级
Nacos KMS阿里云一体化
KMS 服务自建服务统一管理

六、配置规范

6.1 命名规范

yaml
# 推荐用点分隔
spring.datasource.url
spring.datasource.hikari.max-pool-size

# 不推荐(应用层用)
datasourceUrl

6.2 分层管理

yaml
# common.yaml(所有服务共享)
spring.application.name=...
spring.main.banner-mode=off
server.servlet.encoding.charset=UTF-8

# datasource.yaml(基础设施)
spring.datasource.url=...
spring.datasource.username=...

# order-service.yaml(业务)
order.timeout=5000
order.max-retry=3

6.3 必读 vs 可选

yaml
# 必读 → bootstrap.yml(启动时)
spring.application.name
spring.cloud.nacos.config.server-addr
spring.profiles.active

# 可选 → application.yml / Nacos
业务配置、日志级别、连接池参数

6.4 避免敏感信息

yaml
# ❌ 不要把密钥直接写在配置
spring.datasource.password: root123

# ✅ 通过环境变量或加密
spring.datasource.password: ${DB_PASS}

七、监听变更总线:Bus

@RefreshScope 只刷新当前服务实例。Bus 让配置变更广播到所有实例。

xml
<!-- Config Server + Bus -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-monitor</artifactId>
</dependency>
yaml
spring:
  rabbitmq:
    host: localhost
    port: 5672

management:
  endpoints:
    web:
      exposure:
        include: bus-refresh

触发刷新:

bash
curl -X POST http://config-server/actuator/busrefresh

所有服务实例同时收到消息,触发配置刷新。

八、灰度配置推送

Nacos 支持配置灰度发布。

bash
# 通过 Nacos OpenAPI 实现
curl -X POST 'http://nacos:8848/nacos/v1/cs/configs' \
  -d 'dataId=order-service.yaml&group=DEFAULT_GROUP&content=...&beta=true'

九、配置审计

9.1 Nacos 操作审计

控制台 权限管理 → 操作日志 查询变更历史。

9.2 Spring Boot Audit

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
java
@Aspect
@Component
public class ConfigAudit {

    @Autowired
    private AuditLogRepository auditLogRepo;

    @Before("@annotation(org.springframework.cloud.context.config.annotation.RefreshScope)")
    public void auditRefresh(JoinPoint jp) {
        AuditLog log = new AuditLog();
        log.setAction("CONFIG_REFRESH");
        log.setUser(SecurityContextHolder.getContext().getAuthentication().getName());
        auditLogRepo.save(log);
    }
}

十、Spring Cloud 全家桶图

十一、配置最佳实践

11.1 使用 application-{profile}.yaml

yaml
# bootstrap.yml - 只放启动必需的配置
spring:
  cloud:
    nacos:
      config:
        file-extension: yaml

# application-dev.yml
spring:
  datasource:
    url: jdbc:mysql://dev-mysql/...

11.2 启动前必检

java
@Component
public class ConfigValidator implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication app) {
        // 检查关键配置是否存在
        List<String> required = List.of(
            "spring.datasource.url",
            "spring.datasource.password"
        );
        required.forEach(key -> {
            if (env.getProperty(key) == null) {
                throw new IllegalStateException("Missing required config: " + key);
            }
        });
    }
}

11.3 启动失败快速定位

yaml
# 调试模式打印所有配置源
logging:
  level:
    org.springframework.cloud: DEBUG

十二、本章小结

组件作用
Config ServerGit 后端配置中心
Nacos Config一体化(注册+配置)
Apollo携程开源,功能强
@RefreshScopeBean 级配置刷新
Bus全实例刷新广播
Jasypt配置加密

动手练习

  1. 用 Nacos Config 做订单服务的配置中心
  2. 配置动态刷新,修改 Nacos 验证 Bean 自动刷新
  3. 用 Jasypt 加密数据库密码
  4. 写一个监听器,配置变更时清空本地缓存

推荐阅读


下一章:第 226 章:微服务治理 - Sentinel

本站基于 VitePress 构建 · 由 Codebook 团队维护