熔断、降级与限流
微服务调用链中,单点故障可能引发级联雪崩。熔断、降级、限流是保障系统稳定性的三道防线。
1. 熔断器(Circuit Breaker)
状态机
┌─────────┐ 失败率>阈值 ┌─────────┐
│ CLOSED │──────────────→│ OPEN │
│ (正常) │ │ (熔断) │
└────┬────┘ └────┬────┘
│ │
失败计数恢复 │ 超时后
│ ↓
│ ┌─────────────┐
└─────────────────│ HALF-OPEN │
探测失败 │ (半开/探测) │
└─────────────┘
参数配置
| 参数 | 说明 | 典型值 |
|---|---|---|
| failureThreshold | 触发熔断的失败次数/比例 | 5 次或 50% |
| slowCallThreshold | 触发熔断的慢调用比例 | 80% |
| waitDurationInOpenState | OPEN 持续时间 | 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)│
│ ├─ 熔断器 │ │ ├─ 熔断器 │ │ ├─ 熔断器│
│ ├─ 舱壁隔离 │ │ ├─ 舱壁隔离 │ │ └─ 降级 │
│ └─ 降级 │ │ └─ 降级 │ └──────────┘
└─────────────┘ └─────────────┘
分层限流策略:
| 层级 | 限流维度 | 典型阈值 | 响应方式 |
|---|---|---|---|
| CDN | IP + 地域 | 10k req/s | 拒接 + 缓存 |
| Gateway | API + 用户 | 1k req/s/user | 429 Too Many Requests |
| 服务 | 接口 + 租户 | 100 req/s | 排队或快速失败 |
| 数据库 | 连接池 | 50 connections | 连接等待超时 |
从规则限流到自适应智能限流,从被动防护到主动混沌验证,微服务稳定性保障是一个持续演进的过程。建立完善的监控告警体系,结合多维度的防护策略,才能在面对突发流量和依赖故障时从容应对。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。