小陈的知识图谱
SpringL5 实战重要

服务治理与配置中心

服务网格、配置管理、服务降级、灰度发布、全链路压测

服务治理体系概述

什么是服务治理?

微服务架构中,几十上百个服务互相调用,面临的问题:

服务雪崩:A → B → C → D
                    │
                    ▼
                  D 挂了
                    │
                    ▼
          C 等待 D 的响应(线程阻塞)
                    │
                    ▼
          B 等 C,线程池耗尽
                    │
                    ▼
          A 等 B,整个系统不可用 → 雪崩

"三个设计"解决雪崩问题:

服务治理三大法宝:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  限流 (Rate Limiting)   熔断 (Circuit Breaker)   降级 (Degradation)│
│  ┌─────────────────┐  ┌─────────────────┐  ┌────────────────┐ │
│  │ 控制入口流量      │  │ 自动断开故障链路  │  │ 提供兜底方案   │ │
│  │ 防止系统过载      │  │ 防止故障蔓延      │  │ 保证核心功能   │ │
│  │ "限"             │  │ "断"             │  │ "舍"          │ │
│  └─────────────────┘  └─────────────────┘  └────────────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘

---

限流算法详解

四种限流算法对比

┌─────────────────────────────────────────────────────────────┐
│  算法        │ 原理                    │ 特点                │
├─────────────┼─────────────────────────┼─────────────────────┤
│ 固定窗口     │ 每 X 秒最多处理 N 个请求 │ 实现简单,窗口边界有突刺 │
│ 滑动窗口     │ 按时间粒度滑动统计       │ 更平滑,精度可控       │
│ 令牌桶       │ 匀速放入令牌,取到才通过  │ 支持突发流量           │
│ 漏桶         │ 请求进入桶匀速流出       │ 绝对平滑,不支持突发    │
└─────────────────────────────────────────────────────────────┘

固定窗口(计数器)算法:

public class FixedWindowRateLimiter {

    private final long windowSize;       // 窗口大小(毫秒)
    private final int maxRequests;       // 最大请求数
    private int currentCount;            // 当前计数
    private long windowStart;            // 窗口开始时间

    public FixedWindowRateLimiter(long windowSize, int maxRequests) {
        this.windowSize = windowSize;
        this.maxRequests = maxRequests;
        this.windowStart = System.currentTimeMillis();
    }

    public synchronized boolean tryAcquire() {
        long now = System.currentTimeMillis();

        // 超过窗口时间,重置
        if (now - windowStart >= windowSize) {
            windowStart = now;
            currentCount = 0;
        }

        // 检查是否超过阈值
        if (currentCount >= maxRequests) {
            return false;  // 限流
        }

        currentCount++;
        return true;
    }
}

固定窗口问题:在窗口切换的边界可能出现 2 倍突发流量(例如 0:59 和 1:00 各有 100 个请求,实际 1 秒内通过了 200 个)。

滑动窗口算法:

public class SlidingWindowRateLimiter {

    private final int windowSize;        // 窗口大小(秒)
    private final int maxRequests;       // 最大请求数
    private final int slotCount;         // 子窗口数量(精度)
    private final AtomicLongArray slots; // 每个子窗口的计数
    private volatile int currentSlot;    // 当前子窗口索引

    public SlidingWindowRateLimiter(int windowSize, int maxRequests, int slotCount) {
        this.windowSize = windowSize;
        this.maxRequests = maxRequests;
        this.slotCount = slotCount;
        this.slots = new AtomicLongArray(slotCount);
    }

    public boolean tryAcquire() {
        int slot = getCurrentSlot();
        slots.incrementAndGet(slot);

        // 统计整个窗口的请求数
        long total = 0;
        for (int i = 0; i < slotCount; i++) {
            total += slots.get(i);
        }

        return total <= maxRequests;
    }

    private int getCurrentSlot() {
        long now = System.currentTimeMillis();
        return (int) ((now / (windowSize * 1000L / slotCount)) % slotCount);
    }
}

令牌桶算法(常用):

┌──────────────────┐
                          │  令牌桶           │
                          │  ┌──────────────┐ │
  ┌─────────┐  放入令牌      │  │ ● ● ● ● ●  │ │
  │ 令牌生成  │─────────────▶│  │ ● ● ● ●    │ │
  │ 每秒 r 个  │             │  └──────────────┘ │
  └─────────┘              │  容量 = b         │
                            └──────────┬───────┘
                                       │
                          ┌────────────┴────────────┐
                          │  请求到达,取令牌          │
                          │  有令牌 → 放行            │
                          │  无令牌 → 拒绝            │
                          └─────────────────────────┘

// 使用 Guava RateLimiter(令牌桶实现)
public class GuavaRateLimiterDemo {

    // 每秒生成 100 个令牌,桶最大容量 100
    private final RateLimiter rateLimiter = RateLimiter.create(100.0);

    // 预热模式(适用于秒杀等突发场景)
    // 前 10 秒从 50% 速率逐渐提升到满速
    private final RateLimiter warmupLimiter = RateLimiter.create(100.0, 10, TimeUnit.SECONDS);

    public boolean tryAcquire() {
        return rateLimiter.tryAcquire(); // 非阻塞尝试
    }

    public void acquire() {
        double waitTime = rateLimiter.acquire(); // 阻塞等待,返回等待时间
    }
}

---

熔断器(Circuit Breaker)

状态机

正常调用
                 ┌─────────┐
                 │         ▼
           ┌──────────┐
           │  CLOSED  │  (关闭状态:正常调用)
           │  关闭     │
           └─────┬────┘
                 │
                 │ 失败次数 / 比例超阈值
                 ▼
           ┌──────────┐
           │   OPEN   │  (开启状态:直接拒绝)
           │   打开    │
           └─────┬────┘
                 │
                 │ 超时时间到
                 ▼
           ┌──────────┐
           │ HALF_OPEN│  (半开状态:试探恢复)
           │  半开     │
           └─────┬────┘
                 │
        ┌────────┴────────┐
        │                 │
     成功(恢复)        失败(再次熔断)
        │                 │
        ▼                 ▼
    ┌──────────┐    ┌──────────┐
    │  CLOSED  │    │   OPEN   │
    └──────────┘    └──────────┘

Sentinel 熔断规则配置

@Configuration
public class SentinelConfig {

    @PostConstruct
    public void initCircuitBreakerRules() {
        List<DegradeRule> rules = new ArrayList<>();

        // 1. 慢调用比例熔断
        DegradeRule slowCallRule = new DegradeRule("getUserById")
            .setGrade(RuleConstant.DEGRADE_GRADE_RT)        // 按响应时间
            .setCount(200)                                   // 最大 RT 200ms
            .setTimeWindow(60)                               // 熔断时长 60s
            .setMinRequestAmount(5)                          // 最小请求数
            .setSlowRatioThreshold(0.5);                     // 慢调用比例阈值 50%
        rules.add(slowCallRule);

        // 2. 异常比例熔断
        DegradeRule exceptionRule = new DegradeRule("createOrder")
            .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) // 按异常比例
            .setCount(0.2)                                       // 异常比例 20%
            .setTimeWindow(30)                                   // 熔断 30s
            .setMinRequestAmount(10);
        rules.add(exceptionRule);

        // 3. 异常数熔断
        DegradeRule exceptionCountRule = new DegradeRule("payment")
            .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) // 按异常数
            .setCount(50)                                          // 最近 1 分钟 50 个异常
            .setTimeWindow(30)
            .setMinRequestAmount(10);
        rules.add(exceptionCountRule);

        DegradeRuleManager.loadRules(rules);
    }
}

---

服务降级

降级分级策略

降级级别表:
┌────────┬─────────────────────────────────────┐
│ 级别    │ 措施                                │
├────────┼─────────────────────────────────────┤
│ L1     │ 非核心服务降级(日志、监控、推荐)     │
│ L2     │ 写操作降级(评论、点赞改为异步)       │
│ L3     │ 读操作降级(展示缓存/兜底数据)        │
│ L4     │ 功能降级(关闭部分功能,只保留核心业务) │
└────────┴─────────────────────────────────────┘

降级实现示例

@Service
@Slf4j
public class RecommendService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    // 方案 A:直接降级(返回空/默认值)
    @SentinelResource(value = "recommend", fallback = "defaultRecommend")
    public List<Product> getRecommendations(Long userId) {
        // 调用推荐系统(可能耗时较久)
        return recommendClient.getRecommendations(userId);
    }

    // 默认兜底
    public List<Product> defaultRecommend(Long userId, Throwable e) {
        log.warn("推荐系统不可用,返回默认推荐: {}", e.getMessage());
        // 返回缓存的热门商品
        return getHotProductsFromCache();
    }

    // 方案 B:渐进式降级(尝试不同级别)
    public PageResult<Product> searchProducts(String keyword, int page, int size) {
        try {
            // Level 0:正常搜索
            return searchFromES(keyword, page, size);
        } catch (Exception e) {
            log.warn("ES 搜索失败,降级到 MySQL: {}", e.getMessage());
            try {
                // Level 1:降级到 MySQL LIKE 搜索
                return searchFromDB(keyword, page, size);
            } catch (Exception e2) {
                // Level 2:降级到缓存数据
                return searchFromCache(keyword);
            }
        }
    }

    // 方案 C:开关降级(通过配置中心动态控制)
    public Result<?> dynamicDegradation(String key) {
        // 从配置中心读取降级开关
        String degradeLevel = configCenter.getConfig("degrade.recommend.level");

        if ("full".equals(degradeLevel)) {
            return Result.success(Collections.emptyList());  // 完全降级
        }
        if ("simple".equals(degradeLevel)) {
            return Result.success(getSimpleRecommend());     // 简单模式
        }
        return Result.success(getFullRecommend());            // 正常模式
    }
}

---

灰度发布

策略对比

┌──────────────┬─────────────────────┬──────────────────────┐
│   策略        │ 原理                 │ 适用场景              │
├──────────────┼─────────────────────┼──────────────────────┤
│ 蓝绿部署      │ 两套完整环境,切流量   │ 重大版本升级          │
│              │                      │ 快速回滚重要          │
├──────────────┼─────────────────────┼──────────────────────┤
│ 金丝雀发布    │ 先升级少量实例验证     │ 功能验证、性能测试     │
│              │ 逐步扩大范围          │                      │
├──────────────┼─────────────────────┼──────────────────────┤
│ 按比例灰度    │ 5%→20%→50%→100%    │ 功能逐步放量          │
├──────────────┼─────────────────────┼──────────────────────┤
│ 按标签灰度    │ 特定用户/地域/IP灰度  │ 内测、A/B 测试        │
└──────────────┴─────────────────────┴──────────────────────┘

Nacos + Gateway 灰度实现

# 灰度服务元数据配置(在 Nacos 注册时添加)
spring:
  cloud:
    nacos:
      discovery:
        metadata:
          version: v2.0.1                # 灰度版本号
          canary: true                    # 灰度标记

// 灰度路由过滤器
@Component
@Slf4j
public class GrayRouteFilter implements GlobalFilter, Ordered {

    // 灰度用户列表(生产环境从配置中心读取)
    @Value("#{'${gray.users:}'.split(',')}")
    private Set<String> grayUsers;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String userId = request.getHeaders().getFirst("X-User-Id");

        boolean isGray = false;

        // 判断是否灰度用户
        if (userId != null && grayUsers.contains(userId)) {
            isGray = true;
        }

        // 也可以通过 Header 标记(测试专用)
        if ("true".equals(request.getHeaders().getFirst("X-Gray"))) {
            isGray = true;
        }

        log.debug("用户 {} 灰度状态: {}", userId, isGray);

        // 在请求头中加入灰度标记,下游服务根据此标记选择版本
        ServerHttpRequest modifiedRequest = request.mutate()
            .header("X-Gray-Flag", String.valueOf(isGray))
            .build();

        return chain.filter(exchange.mutate().request(modifiedRequest).build());
    }

    @Override
    public int getOrder() {
        return -50;
    }
}

# 灰度路由配置
spring:
  cloud:
    gateway:
      routes:
        # 灰度版本
        - id: order-service-canary
          uri: lb://order-service-canary?canary=true    # 路由到灰度实例
          predicates:
            - Path=/api/order/**
            - Header=X-Gray-Flag, true                  # 只有灰度标记才走
          filters:
            - StripPrefix=1

        # 稳定版本
        - id: order-service-stable
          uri: lb://order-service                        # 路由到稳定实例
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1

自定义 LoadBalancer 灰度规则

// 自定义负载均衡过滤器
@Component
@Slf4j
public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {

    private final String serviceId;

    public GrayLoadBalancer(String serviceId) {
        this.serviceId = serviceId;
    }

    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        // 从 Request 中获取灰度标记
        RequestDataContext context = (RequestDataContext) request.getContext();
        String grayFlag = context.getClientRequest().getHeaders()
            .getFirst("X-Gray-Flag");

        boolean isGray = "true".equals(grayFlag);

        // 获取所有可用实例
        return serviceInstanceListSupplierProvider.get(serviceId)
            .flatMap(supplier -> supplier.get(request))
            .map(instances -> {
                // 灰度请求优先选择灰度实例
                if (isGray) {
                    List<ServiceInstance> grayInstances = instances.stream()
                        .filter(instance -> "true".equals(
                            instance.getMetadata().getOrDefault("canary", "false")))
                        .collect(Collectors.toList());

                    if (!grayInstances.isEmpty()) {
                        return Response.of(selectOne(grayInstances));
                    }
                }

                // 非灰度或没有灰度实例时选择正常实例
                List<ServiceInstance> normalInstances = instances.stream()
                    .filter(instance -> !"true".equals(
                        instance.getMetadata().getOrDefault("canary", "false")))
                    .collect(Collectors.toList());

                return Response.of(selectOne(normalInstances));
            });
    }

    private ServiceInstance selectOne(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            return null;
        }
        // 简单轮询
        return instances.get(ThreadLocalRandom.current().nextInt(instances.size()));
    }
}

---

全链路压测

架构图

压力机 (JMeter / wrk / Locust)
        │
        ▼
┌──────────────────────────┐
│       Gateway            │ ← 识别压测标记 Header
│  识别压测流量 → 添加标记   │
└──────────┬───────────────┘
           │
           ▼
┌──────────────────────────┐
│     User Service         │ ← 传递压测标记
│  正常表:user_0           │
│  影子表:shadow_user_0    │ ← 压测数据写影子表
└──────────┬───────────────┘
           │
           ▼
┌──────────────────────────┐
│     Order Service        │
│  正常表:order_0          │
│  影子表:shadow_order_0   │ ← 不影响线上数据
└──────────┬───────────────┘
           │
           ▼
┌──────────────────────────┐
│       MQ                 │
│  压测消息隔离 (Tag 过滤)  │
└──────────────────────────┘

影子表实现方案

/**
 * 基于 ThreadLocal 的压测上下文
 * 压测标记在整个调用链中传递
 */
@Component
public class PerfTestContext {

    private static final ThreadLocal<Boolean> PERF_FLAG = new ThreadLocal<>();

    // 从请求中识别压测流量
    public boolean isPerfTest(HttpServletRequest request) {
        return "true".equals(request.getHeader("X-Perf-Test"));
    }

    // 从链路追踪标记判断
    public boolean isPerfTestByTrace() {
        return Boolean.TRUE.equals(PERF_FLAG.get());
    }

    public void setPerfFlag(boolean isPerf) {
        PERF_FLAG.set(isPerf);
    }

    public void clear() {
        PERF_FLAG.remove();
    }
}

/**
 * 压测流量数据源路由(读写分离 + 影子库)
 */
@Component
public class PerformanceDataSourceRouter extends AbstractRoutingDataSource {

    @Autowired
    private PerfTestContext perfTestContext;

    @Override
    protected Object determineCurrentLookupKey() {
        // 压测流量 → 影子数据源
        if (perfTestContext.isPerfTestByTrace()) {
            return "shadow";
        }
        return "master";
    }
}

# 多数据源配置
spring:
  datasource:
    # 主库(正常业务)
    master:
      url: jdbc:mysql://master-host:3306/mydb
      username: app
      password: secret

    # 影子库(压测数据)
    shadow:
      url: jdbc:mysql://shadow-host:3306/mydb_shadow
      username: app
      password: secret

---

配置中心最佳实践

Nacos Config 配置

spring:
  application:
    name: user-service
  cloud:
    nacos:
      config:
        server-addr: ${NACOS_ADDR:localhost:8848}
        namespace: ${NAMESPACE:prod}
        group: DEFAULT_GROUP
        file-extension: yaml
        refresh-enabled: true           # 开启配置自动刷新
        shared-configs:                 # 共享配置(多服务共用)
          - data-id: common.yaml
            group: DEFAULT_GROUP
            refresh: true
          - data-id: redis.yaml
            group: SHARED_GROUP
            refresh: true

// 动态刷新配置
@Component
@RefreshScope  // 关键注解:配置变更时自动刷新 Bean
@ConfigurationProperties(prefix = "order")
@Data
public class OrderConfig {

    private int maxOrderPerUser = 10;       // 每人最大订单数
    private int orderTimeoutMinutes = 30;   // 订单超时时间
    private boolean enableAutoCancel = true; // 是否自动取消超时订单
    private List<String> blacklistUsers;    // 黑名单用户
}

// 监听配置变更
@Component
public class ConfigChangeListener {

    @Autowired
    private NacosConfigManager nacosConfigManager;

    @PostConstruct
    public void init() {
        nacosConfigManager.getConfigService().addListener(
            "user-service.yaml", "DEFAULT_GROUP", new Listener() {
                @Override
                public Executor getExecutor() {
                    return Executors.newSingleThreadExecutor();
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("配置变更: {}", configInfo);
                    // 执行配置变更后的操作(如重新加载缓存)
                    reloadConfig();
                }
            }
        );
    }
}

配置隔离与安全

配置隔离策略:

Namespace(环境隔离)
├── dev    命名空间:开发环境
│   ├── user-service 配置
│   └── order-service 配置
├── test   命名空间:测试环境
│   ├── user-service 配置
│   └── order-service 配置
├── prod   命名空间:生产环境
│   ├── user-service 配置
│   └── order-service 配置
│
Group(版本隔离)
├── DEFAULT_GROUP    通用组
├── BLUE_GROUP       蓝组(新版)
├── GREEN_GROUP      绿组(旧版)

Data ID(粒度隔离)
├── user-service.yaml          主配置
├── user-service-db.yaml       数据库配置(敏感)
├── user-service-redis.yaml    Redis 配置(敏感)
└── user-service-secret.yaml   密钥配置(加密)

配置加密方案:

# Jasypt 加密敏感配置
jasypt:
  encryptor:
    password: ${JASYPT_PASSWORD}   # 加密密钥(环境变量传入,不硬编码)
    algorithm: PBEWithMD5AndDES

加密后的配置

spring: datasource: password: ENC(加密后的密文字符串)

---

服务网格(Service Mesh)

Istio 架构

┌──────────────────────────────────────────────────────────────────┐
│                     Istio 控制平面                                │
│                                                                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐        │
│  │ Pilot    │  │ Citadel  │  │ Galley   │  │ Kiali    │        │
│  │ 服务发现  │  │ 证书管理  │  │ 配置校验  │  │ 可视化   │        │
│  │ 流量控制  │  │ 安全认证  │  │ 配置分发  │  │ 拓扑图   │        │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘        │
└──────────────────────────┬───────────────────────────────────────┘
                           │ 控制配置下发
                           ▼
┌──────────────────────────────────────────────────────────────────┐
│                    Istio 数据平面(K8s Pod)                      │
│                                                                  │
│  ┌──────────────────┐    ┌──────────────────┐                    │
│  │ Pod A            │    │ Pod B            │                    │
│  │ ┌────┐ ┌──────┐ │    │ ┌────┐ ┌──────┐ │                    │
│  │ │ App│◀─▶Envoy│ │    │ │ App│◀─▶Envoy│ │                    │
│  │ └────┘ └──────┘ │    │ └────┘ └──────┘ │                    │
│  └────────┬─────────┘    └────────┬─────────┘                    │
│           │                       │                              │
│           └─────── Envoy 之间 mTLS 加密通信 ──────┘              │
│                                                                  │
│  每个 Pod 自动注入 Envoy Sidecar 容器,拦截所有进出流量            │
│  应用代码零感知(零侵入)                                         │
└──────────────────────────────────────────────────────────────────┘

传统微服务 vs Service Mesh

传统微服务框架(Spring Cloud):
┌───────────────────────────────────────────────┐
│  应用代码  (业务逻辑 + 注册发现 + 熔断 + 限流)  │
│  需要引入各种 Starter、注解、配置                │
│  框架升级需要改代码重新编译                      │
│  跨语言困难(只适合 Java)                      │
└───────────────────────────────────────────────┘

Service Mesh(Istio + Envoy):
┌───────────────────────────────────────────────┐
│  应用代码  (只关注业务逻辑)                     │
│  ─────────────────────────────────────────    │
│  Sidecar Proxy(透明拦截所有流量)              │
│  - 服务发现、负载均衡                           │
│  - 熔断、重试、超时控制                          │
│  - 流量拆分、灰度发布                           │
│  - mTLS 加密、访问控制                          │
│  - 指标收集、链路追踪                           │
│  上述能力由 Sidecar + 控制平面提供,应用无感知    │
└───────────────────────────────────────────────┘

Istio 流量控制示例(对比 Spring Cloud 配置)

Spring Cloud 方式(代码侵入):

@SentinelResource(value = "product", blockHandler = "block")
public Product getProduct(Long id) {
    return productClient.getProduct(id);
}

Istio 方式(无代码侵入):

# VirtualService:流量路由
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: product-service
spec:
  hosts:
  - product-service
  http:
  - match:
    - headers:
        X-Canary:
          exact: "true"
    route:
    - destination:
        host: product-service
        subset: v2          # 灰度版本
      weight: 100
  - route:
    - destination:
        host: product-service
        subset: v1          # 稳定版本
      weight: 100


DestinationRule:熔断配置

apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: product-service spec: host: product-service trafficPolicy: connectionPool: tcp: maxConnections: 100 # 最大连接数 http: http1MaxPendingRequests: 10 # 最大等待请求 http2MaxRequests: 1000 # 最大请求数 outlierDetection: # 熔断检测 consecutive5xxErrors: 5 # 连续 5 次 5xx 触发熔断 interval: 30s # 检测间隔 baseEjectionTime: 60s # 驱逐基础时间 maxEjectionPercent: 50 # 最大驱逐比例

---

面试高频题

Q1: 限流、熔断、降级的区别与联系?

A: 限流是控制入口流量防止系统过载(主动);熔断是检测到下游故障时自动断开链路防止故障蔓延(被动);降级是在系统压力大时舍弃非核心功能保证核心可用(主动)。三者配合使用:入口限流 + 故障熔断 + 非核心降级。

Q2: 如何实现灰度发布?

A: 三种方式:1. 网关层:通过 Nacos 元数据标记实例版本,Gateway 根据 Header/Cookie 路由到不同版本。2. 负载均衡层:自定义 LoadBalancer 规则,根据请求特征选择实例。3. K8s/Istio 层:通过 Service Mesh 的 VirtualService/DestinationRule 做流量分发。

Q3: 服务治理在 Spring Cloud 和 Service Mesh 中的实现差异?

A: Spring Cloud 是代码侵入式,需要在业务代码中集成各种 Starter(Sentinel/Feign 等),升级需要改代码。Service Mesh 是透明代理模式,通过 Sidecar 拦截流量,与语言无关,升级只需更新 Sidecar。趋势是从 Spring Cloud 向 Service Mesh 演进。

Q4: 配置中心选型 Nacos vs Apollo?

A: Nacos 轻量级,同时是注册中心和配置中心,适合中小团队。Apollo 功能更丰富(配置界面完善、灰度发布、权限管理、配置审计),适合大型团队。如果已有 Nacos 做注册中心,建议直接用 Nacos Config 减少组件。

Q5: 全链路压测的挑战与方案?

A: 挑战:1. 流量识别——通过 Header 标记压测请求 2. 数据隔离——影子表/影子库,压测数据不影响线上 3. 存储隔离——压测数据最终要清理 4. 第三方依赖——通过 Mock 或压测独有的测试账号隔离。方案:在网关层识别压测标记,通过 ThreadLocal 在整个调用链传递,数据访问层根据标记路由到影子数据源。

核心要点

  • 限流/熔断/降级设计模式
  • 灰度发布方案
  • 全链路压测架构
  • 配置中心最佳实践
  • 服务网格 vs 传统微服务

关联知识点