服务熔断与限流(Sentinel / Hystrix / Resilience4j)
为什么需要熔断与限流
服务雪崩效应
在微服务架构中,服务间调用链可能非常复杂。当某个下游服务发生故障(响应变慢或不可用),调用方会持续阻塞等待,导致自身线程池被耗尽。故障沿调用链向上传播,最终导致整个系统崩溃。
正常情况: Service A → Service B → Service C
故障发生: Service A → Service B ✗(故障)
↓
线程被耗尽 → 请求堆积
↓
Service A 也被拖垮 → 上游服务连带故障资源隔离
熔断与限流的核心目标是通过隔离和保护,防止局部故障扩散为全局故障:
| 机制 | 目标 | 手段 |
|---|---|---|
| 限流 | 保护自身不被过量请求压垮 | 控制流入流量 QPS/TPS |
| 熔断 | 快速屏蔽故障下游,防止级联失败 | 监控调用成功率,达到阈值后快速失败 |
| 隔离 | 将不同资源/服务隔离,故障不相互影响 | 线程池隔离、信号量隔离 |
限流算法对比
计数器 / 滑动窗口
固定窗口计数器
将时间划分为固定窗口(如 1 秒),每个窗口内统计请求数,超过阈值则丢弃。
时间轴: |---1s---||---1s---||---1s---|
请求数: 150 80 200
阈值: 100 100 100
✓ 通过 ✓ 通过 ✗ 限流缺点:存在临界突变问题——窗口切换瞬间可能涌入两倍流量。
滑动窗口计数器
将窗口进一步细分为多个小格子,随时间滑动统计,精度更高。
时间轴(1s 窗口,4 个 250ms 格子):
格子: [0-250] [250-500] [500-750] [750-1000]
↓ 时间滑动,丢弃旧格子,加入新格子
[250-500] [500-750] [750-1000] [1000-1250]对比:
| 算法 | 精度 | 内存开销 | 突刺问题 |
|---|---|---|---|
| 固定窗口 | 低 | 低 | 严重 |
| 滑动窗口(细粒度) | 高 | 中 | 较小 |
漏桶算法
将请求比作水,注入一个固定容量的桶,桶底以恒定速率漏水。桶满则溢出(拒绝请求)。
请求 →→→→→ 漏桶(容量固定)
↓
←←←←← 恒定速率流出 → 处理特点:
- 强制平滑流量,输出速率恒定
- 无法应对突发流量(即使有空闲能力也要排队)
- 适合流量整形(Traffic Shaping)
令牌桶算法
以固定速率向桶中放入令牌,请求需获取令牌才能通过。桶有最大容量,允许一定程度的突发。
定时放入令牌(如 100 个/s)
↓
[⛁ ⛁ ⛁ ⛁ ⛁ ⛁] 令牌桶(最大容量 200)
↑
请求 → 获取令牌 → 通过
请求 → 无令牌 → 等待或拒绝特点:
- 允许突发流量(桶中有积压令牌时)
- 输出平均速率可控
- 应用最广泛(Guava RateLimiter、Sentinel)
自适应限流
基于系统实时状态(CPU 负载、RT、入口 QPS)动态调整限流阈值,无需手工配置。
系统指标监控(CPU、Load、RT)
↓
自适应算法(TCP BBR 思路)
↓
动态计算 QPS 阈值
↓
控制入口流量代表实现:
- Sentinel 的系统自适应保护
- Alibaba 的 TCP BBR 思想
- 可根据系统负载自动降级
熔断器模式
熔断器状态机包含三个状态,核心是防止对故障服务的无效等待。
+──────────┐
│ CLOSED │ ← 正常状态,请求通过
+─────┬─────┘
│ 失败率达到阈值
v
+──────────┐
│ OPEN │ ← 熔断打开,请求快速失败
+─────┬─────┘
│ 超时窗口过后
v
+──────────┐
│ HALF-OPEN │ ← 尝试放行少量请求探测
+─────┬─────┘
│
┌────────┴────────┐
v v
成功(恢复) 失败(再次熔断)
+──────────┐ +──────────┐
│ CLOSED │ │ OPEN │
+──────────+ +──────────+| 状态 | 含义 | 行为 |
|---|---|---|
| Closed | 熔断器关闭 | 请求正常通过,统计失败率 |
| Open | 熔断器打开 | 请求直接快速失败,不发起调用 |
| Half-Open | 半开状态 | 放行少量探测请求,判断服务是否恢复 |
关键参数:
- 失败阈值:触发打开的错误比例或次数
- 熔断超时:Open → Half-Open 的等待时间
- 探测请求数:Half-Open 状态下允许通过的请求数
Sentinel 原理与实战
Sentinel 是阿里巴巴开源的流量控制组件,以"资源"为粒度,提供限流、熔断、系统保护等功能。
核心模型
资源(Resource)
┌── 流控规则(FlowRule)
│ ├── 流控模式:直接 / 关联 / 链路
│ └── 流控效果:快速失败 / Warm Up / 排队等待
│
├── 熔断降级规则(DegradeRule)
│ ├── 慢调用比例
│ ├── 异常比例
│ └── 异常数
│
├── 热点规则(ParamFlowRule)
│
└── 系统规则(SystemRule)
├── Load
├── CPU 使用率
├── 平均 RT
├── 入口 QPS
└── 并发线程数流控模式
| 模式 | 说明 | 使用场景 |
|---|---|---|
| 直接(Direct) | 对资源自身进行限流 | 接口级别的 QPS 控制 |
| 关联(Association) | 当关联资源达到阈值,限流本资源 | 读写冲突场景,写流量高时限流读 |
| 链路(Chain) | 按调用入口限流 | 同一资源被不同上游调用,只对特定上游限流 |
流控效果
| 效果 | 行为 | 适用场景 |
|---|---|---|
| 快速失败 | 超出阈值直接抛出异常 | 默认模式,拒绝速度最快 |
| Warm Up(预热) | 阈值从低到高逐渐增加 | 系统刚启动,需缓慢加载缓存/连接池 |
| 排队等待 | 请求进入队列匀速通过 | 削峰填谷,处理突发流量 |
Warm Up 原理:
阈值
↑
│ ─── 最终阈值(如 1000 QPS)
│ ↗
│ ↗
│ ─── 初始阈值(如 300)↗
│ └──────────────┬──────────────→ 时间
预热时长(如 10s)熔断降级规则
| 策略 | 统计维度 | 阈值条件 | 说明 |
|---|---|---|---|
| 慢调用比例 | RT(响应时间) | 最大 RT + 比例阈值 | RT > 200ms 的比例超过 50% 则熔断 |
| 异常比例 | 异常数 / 总请求 | 比例阈值 | 异常比例超过阈值则熔断 |
| 异常数 | 异常数量 | 计数阈值 | 一分钟内异常数超过阈值则熔断 |
热点参数限流
对同一资源的不同参数值施以不同的限流阈值,防止某些热点 Key 打垮系统。
@SentinelResource("getProduct")
// 对参数 index=0(商品 ID)进行热点限流
@SentinelRestricted(
paramIndex = 0,
defaultCount = 100, // 默认限流 100 QPS
paramConfig = {
@ParamConfig(param = "hotSkuId", count = 10) // 热点商品限流更严格
}
)
public Product getProduct(Long skuId) {
// ...
}系统自适应保护
根据系统负载自动调节入口流量,避免系统级过载。
| 规则类型 | 指标 | 说明 |
|---|---|---|
| Load | 系统 Load1 | 超过阈值且当前并发线程数 > 系统容量时触发 |
| CPU | CPU 使用率 | 超过阈值时触发 |
| RT | 所有入口平均 RT | 超过阈值时触发 |
| 入口 QPS | 所有入口总 QPS | 超过阈值时触发 |
| 并发线程数 | 入口线程数 | 超过阈值时触发 |
Dashboard 控制台
Sentinel 提供图形化控制台,支持实时监控与规则推送。
Sentinel Dashboard(默认端口 8080)
├── 实时监控(QPS、RT、并发数)
├── 流控规则管理(增删改查)
├── 熔断降级规则管理
├── 热点规则管理
├── 系统规则管理
├── 集群流控
└── 机器列表接入方式:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Dashboard 地址
port: 8719 # 客户端上报端口与 Nacos 的动态规则配置
spring:
cloud:
sentinel:
datasource:
ds-flow:
nacos:
server-addr: ${nacos.server-addr}
data-id: ${spring.application.name}-flow-rules
group-id: SENTINEL_GROUP
rule-type: flow # 流控规则
ds-degrade:
nacos:
server-addr: ${nacos.server-addr}
data-id: ${spring.application.name}-degrade-rules
group-id: SENTINEL_GROUP
rule-type: degrade # 熔断规则规则存储在 Nacos 中,修改后实时推送到应用,无需重启。
规则数据示例(Nacos Config):
[
{
"resource": "getProduct",
"limitApp": "default",
"grade": 1,
"count": 1000,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]Hystrix 原理
Hystrix 是 Netflix 开源的熔断隔离框架,目前已进入维护状态(不再发布新功能)。
线程池隔离(舱壁模式)
为每个依赖服务分配独立的线程池,某个依赖的线程池耗尽不影响其他依赖。
Service A
├── 线程池 1 → Service B(10 个线程)
│ 线程池 1 耗尽 → 仅影响 Service B 调用
│
├── 线程池 2 → Service C(10 个线程)
│ Service C 调用不受影响
│
└── 线程池 3 → Service D(5 个线程)信号量隔离
使用信号量控制并发数,不切换线程,开销更小。
Service A
├── 信号量 10 → Service B(调用线程阻塞等待)
└── 信号量 10 → Service C对比
| 特性 | 线程池隔离 | 信号量隔离 |
|---|---|---|
| 线程切换 | 是(独立线程池) | 否(调用方线程) |
| 支持超时 | 是 | 否 |
| 支持异步 | 是 | 否 |
| 开销 | 高(线程上下文切换) | 低 |
| 适用场景 | 高延迟、网络调用 | 低延迟、本地调用 |
Hystrix 现状
Hystrix 已在 2018 年进入维护状态,Netflix 官方推荐迁移到 Resilience4j 或其他方案。不建议在新项目中使用。
Resilience4j 原理
Resilience4j 是一个轻量级、模块化的弹性框架,灵感来自 Hystrix,但设计更优雅。
模块化设计
resilience4j-core
├── resilience4j-circuitbreaker ← 熔断器
├── resilience4j-ratelimiter ← 限流器
├── resilience4j-bulkhead ← 隔离(舱壁)
├── resilience4j-retry ← 重试
├── resilience4j-timelimiter ← 超时控制
├── resilience4j-cache ← 缓存
└── resilience4j-feign ← Feign 集成CircuitBreaker
与标准熔断器状态机一致(Closed → Open → Half-Open),支持滑动窗口统计。
resilience4j:
circuitbreaker:
configs:
default:
sliding-window-size: 10 # 滑动窗口大小
minimum-number-of-calls: 5 # 最少调用次数
failure-rate-threshold: 50 # 失败率阈值(%)
wait-duration-in-open-state: 10s # 熔断超时时间
permitted-number-of-calls-in-half-open-state: 3 # 半开探测数RateLimiter
基于令牌桶算法的限流器。
resilience4j:
ratelimiter:
configs:
default:
limit-for-period: 100 # 周期内最大请求数
limit-refresh-period: 1s # 周期时长
timeout-duration: 500ms # 等待令牌的超时Bulkhead
提供信号量隔离和固定线程池隔离两种模式。
resilience4j:
bulkhead:
configs:
default:
max-concurrent-calls: 10 # 最大并发数
max-wait-duration: 10ms # 等待进入的时长Retry
resilience4j:
retry:
configs:
default:
max-attempts: 3 # 最大重试次数
wait-duration: 500ms # 重试间隔
exponential-backoff-multiplier: 1.5 # 指数退避TimeLimiter
resilience4j:
timelimiter:
configs:
default:
timeout-duration: 2s # 超时时间
cancel-running-future: true # 超时后取消任务组合使用
Resilience4j 支持将多个模块组合,按顺序装饰调用链。
// TimeLimiter → CircuitBreaker → Retry → Bulkhead
Supplier<String> decorated = Decorators
.ofSupplier(() -> service.doSomething())
.withTimeLimiter(timeLimiter)
.withCircuitBreaker(circuitBreaker)
.withRetry(retryConfig)
.withBulkhead(bulkheadConfig)
.decorate();
Try<String> result = Try.ofSupplier(decorated);三大框架对比
| 维度 | Sentinel | Hystrix | Resilience4j |
|---|---|---|---|
| 开源方 | Alibaba | Netflix | 社区 |
| 活跃度 | ⭐⭐⭐⭐⭐ 活跃维护 | ⭐ 已停止维护 | ⭐⭐⭐⭐ 活跃维护 |
| 限流能力 | ⭐⭐⭐⭐⭐ 丰富(多种算法 + 自适应) | ⭐⭐ 仅熔断隔离 | ⭐⭐⭐ RateLimiter 模块 |
| 熔断能力 | ⭐⭐⭐⭐⭐ 支持慢调用/异常/热点 | ⭐⭐⭐⭐ 成熟 | ⭐⭐⭐⭐ 标准实现 |
| 隔离机制 | ⭐⭐⭐⭐ 信号量 + 线程池 | ⭐⭐⭐⭐ 线程池 + 信号量 | ⭐⭐⭐⭐ Bulkhead 模块 |
| 实时监控 | ⭐⭐⭐⭐⭐ Dashboard 控制台 | ⭐⭐⭐ Hystrix Dashboard(已停止维护) | ⭐⭐⭐ 需要集成 Micrometer/Prometheus |
| 动态配置 | ⭐⭐⭐⭐⭐ Nacos / Apollo / ZooKeeper | ⭐⭐ 需自实现 | ⭐⭐⭐⭐ 支持配置中心 |
| 性能 | ⭐⭐⭐⭐⭐ 低延迟 | ⭐⭐⭐ 线程切换开销 | ⭐⭐⭐⭐⭐ 轻量无锁 |
| 运维成本 | 低(控制台 + 动态规则) | 中(需自建监控) | 低(模块化集成简单) |
| 语言 | Java | Java | Java / Kotlin |
| Spring Cloud 集成 | Spring Cloud Alibaba | Spring Cloud Netflix | Spring Cloud Circuit Breaker |
| 推荐场景 | 新项目首选,尤其 Alibaba 技术栈 | 存量项目迁移 | 轻量级/非 Spring 项目 |
选型建议
Sentinel(推荐首选)
○ 功能最全面:限流 + 熔断 + 系统保护 + 热点控制
○ 运维友好:自带 Dashboard 控制台
○ 动态规则:与 Nacos/Apollo 无缝集成
○ 适用于 Alibaba Cloud / Spring Cloud Alibaba 体系
Resilience4j(推荐轻量项目)
○ 模块化设计,依赖最小化
○ 无外部依赖,适合非 Spring 项目
○ 与 Spring Cloud Circuit Breaker 标准集成
Hystrix(不推荐新项目使用)
○ 已停止维护,不再修复 Bug
○ 线程池隔离开销大
○ 仅建议存量项目逐步迁移时保留最佳实践
1. 限流先行:对每个入口接口配置合理的 QPS 阈值
2. 熔断兜底:为每个远程调用配置熔断规则
3. 超时必设:所有 RPC/HTTP 调用必须设置超时时间
4. 隔离分明:核心与非核心服务使用不同线程池
5. 监控完善:接入 Sentinel Dashboard 或 Prometheus + Grafana
6. 动态配置:规则通过配置中心管理,避免硬编码
7. 降级优雅:熔断/限流时提供降级方法(Fallback),返回默认值或缓存数据
8. 逐步调优:上线后根据实际流量数据反复调整阈值