熔断、降级与限流

微服务稳定性保障三大手段:熔断器原理、降级策略、限流算法(令牌桶/漏桶/滑动窗口)及舱壁隔离模式。

熔断、降级与限流

微服务调用链中,单点故障可能引发级联雪崩。熔断、降级、限流是保障系统稳定性的三道防线。

1. 熔断器(Circuit Breaker)

状态机

        ┌─────────┐ 失败率>阈值    ┌─────────┐
        │  CLOSED │──────────────→│  OPEN   │
        │ (正常)   │               │ (熔断)   │
        └────┬────┘               └────┬────┘
             │                         │
      失败计数恢复                      │ 超时后
             │                         ↓
             │                  ┌─────────────┐
             └─────────────────│ HALF-OPEN   │
                探测失败        │ (半开/探测) │
                               └─────────────┘

参数配置

参数说明典型值
failureThreshold触发熔断的失败次数/比例5 次或 50%
slowCallThreshold触发熔断的慢调用比例80%
waitDurationInOpenStateOPEN 持续时间30s
permittedNumberOfCallsInHalfOpenState半开探测次数3

Resilience4j 示例

CircuitBreakerConfig config = CircuitBreakerConfig.custom()
    .failureRateThreshold(50)
    .waitDurationInOpenState(Duration.ofSeconds(30))
    .permittedNumberOfCallsInHalfOpenState(3)
    .slidingWindowSize(100)
    .build();

CircuitBreaker cb = CircuitBreaker.of("orderService", config);

// 装饰调用
Supplier<String> decorated = CircuitBreaker
    .decorateSupplier(cb, () -> orderClient.getOrder(id));
String result = Try.ofSupplier(decorated)
    .recover(throwable -> "fallback_order")
    .get();

2. 降级(Degrade)

当服务不可用或响应过慢时,提供简化替代方案。

降级策略

策略场景示例
返回默认值非核心数据推荐列表为空时返回热门商品
返回缓存读服务从 Redis 读取历史数据
功能裁剪核心功能优先关闭评论功能,保留购买
同步转异步非实时要求订单创建后异步发送通知

Sentinel 降级

// 基于慢调用比例的降级
DegradeRule rule = new DegradeRule("getOrder")
    .setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO)
    .setCount(0.5)           // 慢调用比例阈值
    .setTimeWindow(30)       // 熔断时长(秒)
    .setSlowRatioThreshold(500); // 慢调用阈值(ms)

3. 限流(Rate Limiting)

控制请求速率,防止服务被突发流量击垮。

算法对比

【令牌桶】              【漏桶】                【滑动窗口】
  ┌─────┐              ┌─────┐
  │令牌 │ ← 匀速产生    │请求 │ → 匀速漏出
  └─┬───┘              └──┬──┘
    │ 取令牌              │ 排队
    ▼                    ▼
  服务                  服务
  
  允许突发              平滑流量              精确计数
算法特点适用场景
令牌桶允许突发,平均速率可控大多数限流场景
漏桶强制平滑,无突发需要严格平滑的下游
滑动窗口精确统计窗口内请求短时限流
固定窗口实现简单,存在临界突刺统计精度要求低

Guava RateLimiter

RateLimiter limiter = RateLimiter.create(100); // QPS = 100

// 阻塞获取
limiter.acquire();

// 非阻塞尝试
if (limiter.tryAcquire(10, TimeUnit.MILLISECONDS)) {
    process(request);
} else {
    return "Too Many Requests";
}

分布式限流(Redis + Lua)

-- 滑动窗口限流
local key = KEYS[1]
local now = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local limit = tonumber(ARGV[3])

redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
local count = redis.call('ZCARD', key)

if count < limit then
    redis.call('ZADD', key, now, now)
    redis.call('EXPIRE', key, window)
    return 1  -- 允许
else
    return 0  -- 拒绝
end

4. 舱壁隔离(Bulkhead)

将服务资源划分为独立池,一个池的故障不影响其他池。

无隔离:                          舱壁隔离:
                    
   ┌─────┐         ┌──────┐         ┌──────┐
   │所有请求│         │查询请求│         │写请求│
   └──┬──┘         └───┬──┘         └───┬──┘
      │ 共享线程池        │ 线程池 A       │ 线程池 B
      ▼                ▼                ▼
   ┌─────┐         ┌─────┐         ┌─────┐
   │DB连接│         │DB连接│         │DB连接│
   └─────┘         └─────┘         └─────┘

Resilience4j Bulkhead

ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
    .maxThreadPoolSize(10)
    .coreThreadPoolSize(5)
    .queueCapacity(20)
    .build();

ThreadPoolBulkhead bulkhead = ThreadPoolBulkhead.of("backendA", config);
CompletionStage<String> result = bulkhead.executeSupplier(() -> backendService.call());

5. 组合使用

          请求入站
             ↓
    ┌─────────────────┐
    │  限流(全局/用户)│ ← 第一层:防过载
    └─────────────────┘
             ↓
    ┌─────────────────┐
    │   舱壁隔离       │ ← 第二层:资源隔离
    └─────────────────┘
             ↓
    ┌─────────────────┐
    │   熔断器         │ ← 第三层:故障隔离
    └─────────────────┘
             ↓
    ┌─────────────────┐
    │   降级预案       │ ← 最后防线
    └─────────────────┘

6. 实战:Spring Cloud + Sentinel

spring:
  cloud:
    sentinel:
      transport:
        dashboard: sentinel-dashboard:8080
      datasource:
        flow:
          nacos:
            server-addr: nacos:8848
            dataId: ${spring.application.name}-flow-rules
            rule-type: flow
@RestController
public class OrderController {
    @GetMapping("/orders/{id}")
    @SentinelResource(
        value = "getOrderById",
        blockHandler = "handleBlock",
        fallback = "handleFallback"
    )
    public Order getOrder(@PathVariable Long id) {
        return orderService.getById(id);
    }
    
    public Order handleBlock(Long id, BlockException ex) {
        throw new TooManyRequestsException();
    }
    
    public Order handleFallback(Long id, Throwable ex) {
        return Order.empty(); // 降级
    }
}

总结

手段目标触发条件
限流防止过载请求速率超过阈值
熔断防止故障扩散错误率/慢调用超标
降级有损服务依赖服务异常
隔离资源保护资源竞争

四者配合使用,构建多层防护体系,是微服务高可用的基石。

7. 自适应限流:从规则到智能

传统固定阈值限流无法应对业务波动,自适应限流动态调整阈值:

BBR(Bottleneck Bandwidth and Round-trip)算法

借鉴 TCP 拥塞控制思想,根据系统当前负载动态调整并发量:

// 简化版 BBR 核心逻辑
type BBR struct {
    maxInFlight   int64     // 最大并发
    minRT         float64   // 历史最小响应时间
    lastDropTime  time.Time // 上次丢弃时间
    windowSize    int       // 滑动窗口大小
}

func (b *BBR) Allow() bool {
    // 1. 测量当前系统的 inflight 和 RT
    inflight := atomic.LoadInt64(&b.inflight)
    rt := b.currentRT()

    // 2. 计算当前处理能力上限
    // maxFlight = minRT / RT * 历史最大并发
    maxFlight := int64(b.minRT / rt * float64(b.maxInFlight))

    if inflight >= maxFlight {
        // 3. 超过上限则丢弃并记录
        atomic.AddInt64(&b.dropped, 1)
        b.lastDropTime = time.Now()
        return false
    }
    atomic.AddInt64(&b.inflight, 1)
    return true
}

Go-zero 自适应限流

import "github.com/zeromicro/go-zero/core/limit"

// 自适应限流器:CPU > 80% 或请求延迟上升时自动限流
limiter := limit.NewTokenLimiter(
    1000,           // 每秒令牌数(上限)
    100,            // 桶大小
    redis.NewRedis(...),
    "api_limit_key",
)

if ok, _ := limiter.Allow(); !ok {
    return errors.New("服务过载,请稍后重试")
}
指标说明触发动作
CPU 使用率系统 CPU > 80%降低限流阈值
响应延迟 P99延迟突增 > 2x触发极速降级
错误率5xx 比例 > 5%扩大熔断窗口
队列长度等待请求 > 1000拒绝新请求

8. 多维限流与热点防护

生产环境需要从多个维度进行限流:

// Sentinel 多维限流规则
FlowRule rule1 = new FlowRule("api_order_create")
    .setGrade(RuleConstant.FLOW_GRADE_QPS)
    .setCount(100)           // 接口级:100 QPS
    .setStrategy(RuleConstant.STRATEGY_DIRECT);

FlowRule rule2 = new FlowRule("api_order_create")
    .setGrade(RuleConstant.FLOW_GRADE_QPS)
    .setCount(10)            // 用户级:每用户 10 QPS
    .setStrategy(RuleConstant.STRATEGY_CHAIN)
    .setRefResource("user_id");

FlowRule rule3 = new FlowRule("api_order_create")
    .setGrade(RuleConstant.FLOW_GRADE_QPS)
    .setCount(5)             // 商户级:每商户 5 QPS
    .setStrategy(RuleConstant.STRATEGY_CHAIN)
    .setRefResource("merchant_id");

热点参数限流:防止某个用户/商品 ID 的突发请求击垮服务。

// Sentinel 热点参数限流
ParamFlowRule hotRule = new ParamFlowRule("product_detail")
    .setParamIdx(0)          // 第 0 个参数(productId)
    .setCount(100)           // 默认每个 productId 100 QPS
    .setDurationInSec(1);

// 特殊商品(如秒杀品)独立阈值
hotRule.setParamFlowItemList(Arrays.asList(
    new ParamFlowItem("SKU_999", 5, 1),   // 秒杀品:5 QPS
    new ParamFlowItem("SKU_001", 500, 1)  // 热门品:500 QPS
));

9. 监控告警与可观测性

稳定性保障体系的有效性依赖实时监控:

Prometheus 监控指标设计

# 熔断器指标
- name: circuit_breaker_state
  help: "Current state of circuit breaker (0=closed, 1=open, 2=half-open)"
  labels: [service, method]

- name: circuit_breaker_failures_total
  help: "Total number of failures"
  labels: [service, method, exception_type]

# 限流指标
- name: rate_limit_rejected_total
  help: "Total number of rejected requests"
  labels: [api, dimension, limit_type]

- name: rate_limit_allowed_total
  help: "Total number of allowed requests"

# 降级指标
- name: degrade_fallback_total
  help: "Total number of fallback invocations"
  labels: [service, fallback_type]

# 资源隔离指标
- name: bulkhead_active_executions
  help: "Current active executions in bulkhead"
  labels: [bulkhead_name]

- name: bulkhead_queue_wait_time_seconds
  help: "Time spent waiting in bulkhead queue"

Grafana 告警规则

# 熔断器长时间处于 OPEN 状态
groups:
  - name: stability
    rules:
      - alert: CircuitBreakerOpenTooLong
        expr: circuit_breaker_state == 1
        for: 5m
        annotations:
          summary: "熔断器已连续开启超过 5 分钟"

      - alert: HighRateLimitRejection
        expr: rate(rate_limit_rejected_total[1m]) > 100
        for: 2m
        annotations:
          summary: "限流拒绝率过高,可能需要扩容"

      - alert: SlowCallRatioHigh
        expr: |
          (
            rate(circuit_breaker_slow_calls_total[5m])
            /
            rate(circuit_breaker_calls_total[5m])
          ) > 0.8
        annotations:
          summary: "慢调用比例超过 80%,触发降级"

10. 混沌工程:主动验证韧性

通过故意注入故障来验证防护体系的有效性:

# Chaos Mesh 实验:模拟网络延迟
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: payment-service-delay
spec:
  action: delay
  mode: all
  selector:
    namespaces:
      - production
    labelSelectors:
      app: payment-service
  delay:
    latency: "500ms"
    jitter: "100ms"
  duration: "10m"

混沌实验原则:

  • 从开发环境开始,逐步推进到生产(建议生产流量 < 1%)
  • 每次只注入一种故障,观测系统行为
  • 设置自动终止条件(错误率 > 10% 立即停止)
  • 实验后复盘,修复发现的盲区

11. 全链路防护架构

                    ┌──────────────────┐
                    │   CDN / WAF      │ ← 边缘防护:DDoS / Bot 检测
                    └────────┬─────────┘
                             │
                    ┌────────▼─────────┐
                    │   API Gateway    │ ← 第一层:全局限流 + 认证
                    │  (10000 QPS)     │
                    └────────┬─────────┘
                             │
              ┌──────────────┼──────────────┐
              │              │              │
     ┌────────▼────┐  ┌──────▼──────┐ ┌────▼─────┐
     │  订单服务    │  │  库存服务    │ │ 支付服务  │
     │ (限流 500)  │  │ (限流 300)  │ │(限流 200)│
     │  ├─ 熔断器  │  │  ├─ 熔断器   │ │ ├─ 熔断器│
     │  ├─ 舱壁隔离 │  │  ├─ 舱壁隔离  │ │ └─ 降级  │
     │  └─ 降级    │  │  └─ 降级     │ └──────────┘
     └─────────────┘  └─────────────┘

分层限流策略:

层级限流维度典型阈值响应方式
CDNIP + 地域10k req/s拒接 + 缓存
GatewayAPI + 用户1k req/s/user429 Too Many Requests
服务接口 + 租户100 req/s排队或快速失败
数据库连接池50 connections连接等待超时

从规则限流到自适应智能限流,从被动防护到主动混沌验证,微服务稳定性保障是一个持续演进的过程。建立完善的监控告警体系,结合多维度的防护策略,才能在面对突发流量和依赖故障时从容应对。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「架构」更多文章

  1. 韧性工程与错误预算:从 SLO 到故障演练
  2. 微前端架构:组合、隔离与独立部署
  3. 数据网格(Data Mesh):领域数据产品与去中心化治理