5.1 配置中心概述

什么是配置中心

配置中心是微服务架构中用于集中管理应用程序配置的组件。它提供了统一的配置存储、版本控制、动态更新和环境隔离等功能,解决了传统配置管理的痛点。

配置中心的作用

┌─────────────────────────────────────────────────────────────────┐
│                        配置中心架构图                            │
├─────────────────────────────────────────────────────────────────┤
│  开发人员                                                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │
│  │   开发环境   │  │   测试环境   │  │   生产环境   │             │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘             │
│         │                │                │                    │
│         └────────────────┼────────────────┘                    │
│                          │                                     │
│                          ▼                                     │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                  配置中心                               │   │
│  │  ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │   │
│  │  │   配置存储   │ │   版本控制   │ │     权限管理        │ │   │
│  │  └─────────────┘ └─────────────┘ └─────────────────────┘ │   │
│  │  ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │   │
│  │  │   动态刷新   │ │   环境隔离   │ │     配置审计        │ │   │
│  │  └─────────────┘ └─────────────┘ └─────────────────────┘ │   │
│  └─────────────────────┬───────────────────────────────────┘   │
├────────────────────────┼───────────────────────────────────────┤
│                        │ 配置拉取/推送                          │
│                        ▼                                       │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐ │
│  │ User Service    │  │ Product Service │  │ Order Service   │ │
│  │ Config Client   │  │ Config Client   │  │ Config Client   │ │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

核心功能

  1. 集中管理:统一存储和管理所有服务的配置信息
  2. 环境隔离:支持开发、测试、生产等多环境配置
  3. 动态刷新:支持配置的热更新,无需重启服务
  4. 版本控制:配置变更的版本管理和回滚
  5. 权限控制:细粒度的配置访问权限管理
  6. 配置审计:配置变更的审计日志
  7. 高可用:配置中心的集群部署和故障转移
  8. 安全加密:敏感配置的加密存储

传统配置管理的问题

  1. 配置分散:配置文件散布在各个服务中,难以统一管理
  2. 环境混乱:不同环境的配置容易混淆
  3. 更新困难:配置变更需要重新部署服务
  4. 版本管理:缺乏配置的版本控制和回滚机制
  5. 安全风险:敏感配置明文存储,存在安全隐患

5.2 Spring Cloud Config

Config简介

Spring Cloud Config是Spring Cloud生态系统中的配置管理解决方案,提供了服务端和客户端的支持,可以集中管理各个环境的配置文件。

核心组件

  1. Config Server:配置服务端,提供配置的存储和访问
  2. Config Client:配置客户端,从Config Server获取配置
  3. 配置仓库:存储配置文件的仓库(Git、SVN、本地文件系统等)

5.3 Config Server搭建

1. 创建Config Server项目

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/>
    </parent>
    
    <groupId>com.example</groupId>
    <artifactId>config-server</artifactId>
    <version>1.0.0</version>
    <name>config-server</name>
    <description>Configuration Server</description>
    
    <properties>
        <java.version>11</java.version>
        <spring-cloud.version>2021.0.3</spring-cloud.version>
    </properties>
    
    <dependencies>
        <!-- Config Server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        
        <!-- Eureka Client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        
        <!-- Security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        
        <!-- Actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        
        <!-- Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- Validation -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        
        <!-- Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2. 启动类

ConfigServerApplication.java

package com.example.configserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * 配置中心服务端启动类
 */
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

3. 配置文件

application.yml

server:
  port: 8888

spring:
  application:
    name: config-server
  
  # 配置仓库
  cloud:
    config:
      server:
        git:
          # Git仓库地址
          uri: https://github.com/your-username/config-repo.git
          # 搜索路径
          search-paths: '{application}'
          # 默认分支
          default-label: main
          # 用户名和密码(私有仓库)
          username: your-username
          password: your-password
          # 克隆超时时间
          timeout: 10
          # 强制拉取
          force-pull: true
          # 删除未跟踪的分支
          delete-untracked: true
          # 本地仓库路径
          basedir: /tmp/config-repo
        
        # 本地文件系统配置(开发环境)
        native:
          search-locations: classpath:/config/,file:./config/
        
        # 健康检查
        health:
          repositories:
            user-service:
              label: main
              name: user-service
              profiles: dev
        
        # 加密配置
        encrypt:
          enabled: true
  
  # 安全配置
  security:
    user:
      name: config-admin
      password: config-password
      roles: ADMIN

# Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${server.port}
    lease-renewal-interval-in-seconds: 10
    lease-expiration-duration-in-seconds: 30

# 监控配置
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always
    configprops:
      show-values: always

# 日志配置
logging:
  level:
    org.springframework.cloud.config: DEBUG
    org.springframework.web: DEBUG
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

4. 安全配置

SecurityConfig.java

package com.example.configserver.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

/**
 * 安全配置
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/actuator/health", "/actuator/info").permitAll()
                .anyRequest().authenticated()
            )
            .httpBasic();
        
        return http.build();
    }
}

5.4 配置仓库结构

Git仓库结构

config-repo/
├── application.yml                 # 全局默认配置
├── application-dev.yml             # 全局开发环境配置
├── application-test.yml            # 全局测试环境配置
├── application-prod.yml            # 全局生产环境配置
├── user-service/
│   ├── user-service.yml            # 用户服务默认配置
│   ├── user-service-dev.yml        # 用户服务开发环境配置
│   ├── user-service-test.yml       # 用户服务测试环境配置
│   └── user-service-prod.yml       # 用户服务生产环境配置
├── product-service/
│   ├── product-service.yml
│   ├── product-service-dev.yml
│   ├── product-service-test.yml
│   └── product-service-prod.yml
└── order-service/
    ├── order-service.yml
    ├── order-service-dev.yml
    ├── order-service-test.yml
    └── order-service-prod.yml

配置文件示例

全局配置 - application.yml

# 全局默认配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      idle-timeout: 300000
      connection-timeout: 20000
      max-lifetime: 1200000
  
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect
        format_sql: true
  
  redis:
    timeout: 2000ms
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: -1ms

# 日志配置
logging:
  level:
    com.example: INFO
    org.springframework.web: WARN
    org.hibernate.SQL: WARN
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
    file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

# 监控配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  endpoint:
    health:
      show-details: when-authorized

开发环境配置 - application-dev.yml

# 开发环境全局配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/microservice_dev?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: dev_user
    password: '{cipher}AQA...encrypted_password...'
  
  redis:
    host: localhost
    port: 6379
    database: 0
  
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

# 日志配置
logging:
  level:
    com.example: DEBUG
    org.springframework.web: DEBUG
    org.hibernate.SQL: DEBUG
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
  file:
    name: logs/application-dev.log

# 监控配置
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always

用户服务配置 - user-service.yml

# 用户服务默认配置
server:
  port: 8081

spring:
  application:
    name: user-service
  
  datasource:
    hikari:
      maximum-pool-size: 10
  
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

# 业务配置
user:
  service:
    # 密码加密盐值
    password-salt: '{cipher}AQB...encrypted_salt...'
    # JWT配置
    jwt:
      secret: '{cipher}AQC...encrypted_jwt_secret...'
      expiration: 86400
    # 验证码配置
    captcha:
      enabled: true
      length: 4
      expire-time: 300
    # 邮件配置
    email:
      enabled: true
      smtp:
        host: smtp.example.com
        port: 587
        username: noreply@example.com
        password: '{cipher}AQD...encrypted_email_password...'

# Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${server.port}

用户服务开发环境配置 - user-service-dev.yml

# 用户服务开发环境配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/user_service_dev?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: user_dev
    password: '{cipher}AQE...encrypted_dev_password...'
  
  redis:
    database: 1

# 业务配置
user:
  service:
    # 开发环境允许跳过验证码
    captcha:
      enabled: false
    # 开发环境邮件配置
    email:
      enabled: false
      # 使用控制台输出代替真实邮件发送
      mock: true

# 日志配置
logging:
  level:
    com.example.userservice: DEBUG

5.5 Config Client配置

1. 添加依赖

pom.xml

<!-- Config Client -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

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

<!-- Actuator for refresh -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2. Bootstrap配置

bootstrap.yml

spring:
  application:
    name: user-service
  
  profiles:
    active: dev
  
  cloud:
    config:
      # Config Server地址
      uri: http://localhost:8888
      # 配置文件名(默认为应用名)
      name: ${spring.application.name}
      # 环境(对应profiles)
      profile: ${spring.profiles.active}
      # 分支
      label: main
      # 认证信息
      username: config-admin
      password: config-password
      # 快速失败
      fail-fast: true
      # 重试配置
      retry:
        initial-interval: 1000
        max-attempts: 6
        max-interval: 2000
        multiplier: 1.1
      # 请求超时
      request-connect-timeout: 5000
      request-read-timeout: 10000

# Eureka配置(用于服务发现Config Server)
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

3. 动态刷新配置

配置类

UserServiceConfig.java

package com.example.userservice.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

/**
 * 用户服务配置
 */
@Component
@ConfigurationProperties(prefix = "user.service")
@RefreshScope
@Data
public class UserServiceConfig {
    
    private String passwordSalt;
    
    private JwtConfig jwt = new JwtConfig();
    
    private CaptchaConfig captcha = new CaptchaConfig();
    
    private EmailConfig email = new EmailConfig();
    
    @Data
    public static class JwtConfig {
        private String secret;
        private Long expiration;
    }
    
    @Data
    public static class CaptchaConfig {
        private Boolean enabled;
        private Integer length;
        private Integer expireTime;
    }
    
    @Data
    public static class EmailConfig {
        private Boolean enabled;
        private Boolean mock;
        private SmtpConfig smtp = new SmtpConfig();
        
        @Data
        public static class SmtpConfig {
            private String host;
            private Integer port;
            private String username;
            private String password;
        }
    }
}

配置刷新端点

application.yml

# 监控配置
management:
  endpoints:
    web:
      exposure:
        include: refresh,health,info
  endpoint:
    refresh:
      enabled: true

配置刷新控制器

ConfigController.java

package com.example.userservice.controller;

import com.example.userservice.config.UserServiceConfig;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Set;

/**
 * 配置管理控制器
 */
@RestController
@RequestMapping("/config")
@RequiredArgsConstructor
public class ConfigController {
    
    private final UserServiceConfig userServiceConfig;
    private final ContextRefresher contextRefresher;
    
    /**
     * 获取当前配置
     */
    @GetMapping("/current")
    public UserServiceConfig getCurrentConfig() {
        return userServiceConfig;
    }
    
    /**
     * 手动刷新配置
     */
    @PostMapping("/refresh")
    public Set<String> refreshConfig() {
        return contextRefresher.refresh();
    }
}

5.6 配置加密

1. 加密配置

生成密钥

application.yml

spring:
  cloud:
    config:
      server:
        encrypt:
          enabled: true
        # 对称加密
        encrypt:
          key: myEncryptionKey123456
        # 非对称加密(推荐生产环境)
        # encrypt:
        #   key-store:
        #     location: classpath:config-server.jks
        #     password: keystorepass
        #     alias: config-server-key
        #     secret: keypass

加密工具类

EncryptionUtil.java

package com.example.configserver.util;

import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.security.crypto.keygen.KeyGenerators;

/**
 * 配置加密工具类
 */
public class EncryptionUtil {
    
    private static final String ENCRYPTION_KEY = "myEncryptionKey123456";
    
    /**
     * 加密文本
     */
    public static String encrypt(String plainText) {
        String salt = KeyGenerators.string().generateKey();
        TextEncryptor encryptor = Encryptors.text(ENCRYPTION_KEY, salt);
        return salt + encryptor.encrypt(plainText);
    }
    
    /**
     * 解密文本
     */
    public static String decrypt(String encryptedText) {
        String salt = encryptedText.substring(0, 16);
        String encrypted = encryptedText.substring(16);
        TextEncryptor encryptor = Encryptors.text(ENCRYPTION_KEY, salt);
        return encryptor.decrypt(encrypted);
    }
    
    public static void main(String[] args) {
        // 加密示例
        String password = "mySecretPassword";
        String encrypted = encrypt(password);
        System.out.println("Encrypted: " + encrypted);
        
        String decrypted = decrypt(encrypted);
        System.out.println("Decrypted: " + decrypted);
    }
}

2. 使用加密配置

加密敏感配置

# 使用Config Server的加密端点
curl -X POST http://config-admin:config-password@localhost:8888/encrypt \
  -H "Content-Type: text/plain" \
  -d "mySecretPassword"

# 返回加密后的值
AQA1234567890abcdef...

在配置文件中使用

# 使用{cipher}前缀标识加密值
spring:
  datasource:
    password: '{cipher}AQA1234567890abcdef...'

user:
  service:
    jwt:
      secret: '{cipher}AQB9876543210fedcba...'

5.7 配置监听与自动刷新

1. Spring Cloud Bus

添加依赖

pom.xml

<!-- Spring Cloud Bus -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

配置消息总线

application.yml

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
  
  cloud:
    bus:
      enabled: true
      refresh:
        enabled: true
      env:
        enabled: true

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

2. Git Webhook自动刷新

Webhook控制器

WebhookController.java

package com.example.configserver.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * Git Webhook控制器
 */
@RestController
@RequestMapping("/webhook")
@RequiredArgsConstructor
@Slf4j
public class WebhookController {
    
    private final ApplicationEventPublisher publisher;
    
    /**
     * GitHub Webhook
     */
    @PostMapping("/github")
    public String githubWebhook(@RequestBody Map<String, Object> payload) {
        log.info("Received GitHub webhook: {}", payload);
        
        // 检查是否是配置文件变更
        if (isConfigChange(payload)) {
            // 发布刷新事件
            publisher.publishEvent(new RefreshRemoteApplicationEvent(
                this, "config-server", "**"));
            
            log.info("Configuration refresh event published");
            return "Configuration refreshed";
        }
        
        return "No configuration changes detected";
    }
    
    /**
     * GitLab Webhook
     */
    @PostMapping("/gitlab")
    public String gitlabWebhook(@RequestBody Map<String, Object> payload) {
        log.info("Received GitLab webhook: {}", payload);
        
        // 类似GitHub的处理逻辑
        if (isConfigChange(payload)) {
            publisher.publishEvent(new RefreshRemoteApplicationEvent(
                this, "config-server", "**"));
            
            log.info("Configuration refresh event published");
            return "Configuration refreshed";
        }
        
        return "No configuration changes detected";
    }
    
    private boolean isConfigChange(Map<String, Object> payload) {
        // 检查提交中是否包含配置文件变更
        // 这里简化处理,实际应该检查具体的文件路径
        return true;
    }
}

3. 配置变更监听

配置变更事件监听器

ConfigChangeListener.java

package com.example.userservice.listener;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * 配置变更事件监听器
 */
@Component
@Slf4j
public class ConfigChangeListener {
    
    /**
     * 监听环境变更事件
     */
    @EventListener
    public void handleEnvironmentChange(EnvironmentChangeEvent event) {
        Set<String> changedKeys = event.getKeys();
        log.info("Configuration changed, keys: {}", changedKeys);
        
        // 处理特定配置的变更
        for (String key : changedKeys) {
            if (key.startsWith("user.service.jwt")) {
                log.info("JWT configuration changed, key: {}", key);
                // 重新初始化JWT相关组件
                reinitializeJwtComponents();
            } else if (key.startsWith("user.service.email")) {
                log.info("Email configuration changed, key: {}", key);
                // 重新初始化邮件相关组件
                reinitializeEmailComponents();
            }
        }
    }
    
    private void reinitializeJwtComponents() {
        // 重新初始化JWT组件的逻辑
        log.info("Reinitializing JWT components...");
    }
    
    private void reinitializeEmailComponents() {
        // 重新初始化邮件组件的逻辑
        log.info("Reinitializing email components...");
    }
}

5.8 多环境配置管理

1. 环境配置策略

配置文件命名规范

{application}-{profile}.yml

示例:
- user-service.yml          # 默认配置
- user-service-dev.yml      # 开发环境
- user-service-test.yml     # 测试环境
- user-service-staging.yml  # 预发布环境
- user-service-prod.yml     # 生产环境

配置优先级

  1. 特定环境的应用配置:{application}-{profile}.yml
  2. 应用默认配置:{application}.yml
  3. 特定环境的全局配置:application-{profile}.yml
  4. 全局默认配置:application.yml

2. 环境隔离配置

开发环境配置

user-service-dev.yml

# 开发环境配置
spring:
  datasource:
    url: jdbc:mysql://dev-db:3306/user_service_dev
    username: dev_user
    password: '{cipher}dev_encrypted_password'
  
  redis:
    host: dev-redis
    port: 6379
    database: 0
  
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

# 开发环境特定配置
user:
  service:
    captcha:
      enabled: false  # 开发环境禁用验证码
    email:
      mock: true      # 使用模拟邮件发送

# 日志配置
logging:
  level:
    com.example: DEBUG
    org.hibernate.SQL: DEBUG

测试环境配置

user-service-test.yml

# 测试环境配置
spring:
  datasource:
    url: jdbc:mysql://test-db:3306/user_service_test
    username: test_user
    password: '{cipher}test_encrypted_password'
  
  redis:
    host: test-redis
    port: 6379
    database: 1
  
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

# 测试环境特定配置
user:
  service:
    captcha:
      enabled: true
      length: 4
    email:
      enabled: true
      mock: false

# 日志配置
logging:
  level:
    com.example: INFO
    org.hibernate.SQL: WARN

生产环境配置

user-service-prod.yml

# 生产环境配置
spring:
  datasource:
    url: jdbc:mysql://prod-db-cluster:3306/user_service_prod
    username: prod_user
    password: '{cipher}prod_encrypted_password'
    hikari:
      maximum-pool-size: 50
      minimum-idle: 10
  
  redis:
    cluster:
      nodes:
        - prod-redis-1:6379
        - prod-redis-2:6379
        - prod-redis-3:6379
    password: '{cipher}redis_cluster_password'
  
  jpa:
    hibernate:
      ddl-auto: none
    show-sql: false

# 生产环境特定配置
user:
  service:
    captcha:
      enabled: true
      length: 6
      expire-time: 300
    email:
      enabled: true
      mock: false
      smtp:
        host: smtp.prod.example.com
        port: 587
        username: noreply@example.com
        password: '{cipher}prod_email_password'

# 日志配置
logging:
  level:
    com.example: WARN
    org.hibernate.SQL: ERROR
  file:
    name: /var/log/user-service/application.log
    max-size: 100MB
    max-history: 30

3. 配置管理最佳实践

配置分层管理

ConfigurationManager.java

package com.example.userservice.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Arrays;

/**
 * 配置管理器
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ConfigurationManager {
    
    private final Environment environment;
    
    @PostConstruct
    public void logConfiguration() {
        String[] activeProfiles = environment.getActiveProfiles();
        String[] defaultProfiles = environment.getDefaultProfiles();
        
        log.info("Active profiles: {}", Arrays.toString(activeProfiles));
        log.info("Default profiles: {}", Arrays.toString(defaultProfiles));
        
        // 记录关键配置信息(不包含敏感信息)
        logKeyConfiguration();
    }
    
    private void logKeyConfiguration() {
        log.info("Database URL: {}", 
                environment.getProperty("spring.datasource.url"));
        log.info("Redis host: {}", 
                environment.getProperty("spring.redis.host"));
        log.info("Captcha enabled: {}", 
                environment.getProperty("user.service.captcha.enabled"));
        log.info("Email enabled: {}", 
                environment.getProperty("user.service.email.enabled"));
    }
    
    /**
     * 获取配置值,支持默认值
     */
    public String getProperty(String key, String defaultValue) {
        return environment.getProperty(key, defaultValue);
    }
    
    /**
     * 检查是否为生产环境
     */
    public boolean isProductionEnvironment() {
        return Arrays.asList(environment.getActiveProfiles()).contains("prod");
    }
    
    /**
     * 检查是否为开发环境
     */
    public boolean isDevelopmentEnvironment() {
        return Arrays.asList(environment.getActiveProfiles()).contains("dev");
    }
}

5.9 总结

核心概念回顾

  1. 配置中心的作用

    • 集中管理:统一存储和管理所有服务的配置
    • 环境隔离:支持多环境的配置管理
    • 动态刷新:支持配置的热更新
    • 版本控制:配置变更的版本管理和回滚
    • 安全加密:敏感配置的加密存储
  2. Spring Cloud Config组件

    • Config Server:配置服务端,提供配置的存储和访问
    • Config Client:配置客户端,从Config Server获取配置
    • 配置仓库:存储配置文件的仓库(Git、SVN等)
  3. 配置刷新机制

    • 手动刷新:通过Actuator端点手动触发
    • 自动刷新:通过Spring Cloud Bus实现自动刷新
    • Webhook刷新:通过Git Webhook实现配置变更自动刷新

最佳实践

  1. 配置文件组织

    • 使用清晰的命名规范
    • 合理的目录结构
    • 配置分层管理
    • 环境配置隔离
  2. 安全管理

    • 敏感配置加密存储
    • 配置访问权限控制
    • 配置变更审计日志
    • 使用HTTPS传输
  3. 高可用设计

    • Config Server集群部署
    • 配置本地缓存
    • 故障转移机制
    • 监控和告警
  4. 配置管理流程

    • 配置变更审批流程
    • 配置版本管理
    • 配置回滚机制
    • 配置测试验证

注意事项

  1. 性能考虑

    • 配置缓存策略
    • 网络超时设置
    • 批量配置更新
    • 配置大小限制
  2. 安全防护

    • 配置传输加密
    • 访问权限控制
    • 敏感信息脱敏
    • 配置审计日志
  3. 运维管理

    • 配置变更通知
    • 配置监控告警
    • 配置备份恢复
    • 配置文档管理

扩展方向

  1. 高级功能

    • 配置模板管理
    • 配置继承机制
    • 配置验证规则
    • 配置A/B测试
  2. 集成方案

    • 集成Nacos配置中心
    • 集成Apollo配置中心
    • 集成Consul配置中心
    • 集成Kubernetes ConfigMap

通过本章学习,你应该掌握了Spring Cloud Config的核心概念和实际应用。配置中心是微服务架构中的重要基础设施,合理的配置管理能够显著提升系统的可维护性和运维效率。

下一章我们将学习消息总线,了解如何在微服务架构中实现事件驱动和消息通信。