服务熔断 · 降级 · 限流

分布式系统中,弹性设计的三大核心模式。它们共同构成系统的「免疫系统」,让服务在面对故障和压力时优雅降级而非直接崩溃。

🔌

服务熔断

Circuit Breaker

像家庭电闸:当电流过载时自动跳闸,避免烧毁整个电路。当下游服务频繁失败时,主动切断调用链路。

🪂

服务降级

Fallback / Degradation

像备用降落伞:主伞打不开时,备伞确保安全着陆。当服务无法正常响应时,返回兜底数据保证体验。

🚦

服务限流

Rate Limiting

像高速公路收费站:控制单位时间通过的车辆数。当流量暴增时,限制进入以保护系统容量。

一句话定位

熔断:下游坏了,我主动断开。
被动响应 · 防止级联
降级:能力不够,降低质量。
主动应对 · 保证可用
限流:请求太多,限制进入。
事先预防 · 控制容量
核心问题域

各自解决什么问题?

维度 服务熔断 服务降级 服务限流
核心问题 级联故障 一个服务挂了,拖垮整个调用链 资源瓶颈 系统过载时核心链路受影响 流量冲击 突发流量超过系统承载上限
触发条件 调用失败率 / 慢调用比例超过阈值 系统负载高 / 依赖不可用 / 熔断触发 QPS超过预设阈值
动作时机 事中响应(已经出问题) 事中兜底(问题发生后保底) 事前拦截(还没进来就拦)
保护对象 调用方(防止被下游拖死) 被调方 & 调用方(整体可用性) 被调方(防止被打垮)
典型场景 支付服务挂了 → 订单服务熔断支付调用 推荐服务超时 → 返回热门商品列表 秒杀开始瞬间 → 网关限流 10000 QPS
恢复机制 半开探测,成功则恢复 条件消失后自动恢复 下一个时间窗口自动重置
一、服务熔断 Circuit Breaker
当下游故障时,快速失败而不是傻等,防止级联雪崩

熔断器状态机

熔断器有三个核心状态,自动流转:

关闭 CLOSED
正常调用
打开 OPEN
快速失败
半开 HALF-OPEN
试探调用
关闭 CLOSED
恢复正常

👆 点击 CLOSED 状态模拟故障,观察状态流转

CLOSED → OPEN

在滑动时间窗口内,失败率达到阈值(如 50%),熔断器打开。此后所有请求直接返回错误(快速失败),不再调用下游。

OPEN → HALF-OPEN

经过一段冷却时间(如 10s),熔断器进入半开状态。允许少量试探请求通过。

HALF-OPEN → CLOSED / OPEN

试探请求成功 → 关闭熔断器,恢复正常。试探请求仍失败 → 重新打开熔断器,再次进入冷却等待。

关键配置参数

参数说明典型值
failureRateThreshold触发熔断的失败率阈值50%
slidingWindowSize滑动窗口大小(统计多少请求)100
minimumNumberOfCalls最小调用次数(窗口内需累积足够样本)20
waitDurationInOpenState熔断打开后的冷却时间10s
permittedNumberOfCallsInHalfOpenState半开状态允许的试探请求数5
slowCallDurationThreshold慢调用时间阈值3s
slowCallRateThreshold慢调用比例阈值50%
关键设计理念:熔断器不是一失败就断开。需要 minimumNumberOfCalls 确保统计有足够的样本量,failureRateThreshold 允许一定比例失败(因为网络抖动是正常的),避免因偶然波动误触发。

代码实现示例

Java // Resilience4j CircuitBreaker 配置与使用 import io.github.resilience4j.circuitbreaker.*; import java.time.Duration; // 1. 配置熔断器 CircuitBreakerConfig config = CircuitBreakerConfig.custom() .failureRateThreshold(50) // 失败率阈值 50% .slowCallRateThreshold(50) // 慢调用比例 50% .slowCallDurationThreshold(Duration.ofSeconds(3)) // 超过3秒算慢调用 .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) .slidingWindowSize(100) // 统计最近100次调用 .minimumNumberOfCalls(20) // 至少20次才判断 .waitDurationInOpenState(Duration.ofSeconds(10)) // OPEN→HALF_OPEN 冷却10s .permittedNumberOfCallsInHalfOpenState(5) // 半开时放行5个试探 .build(); // 2. 创建熔断器 CircuitBreaker circuitBreaker = CircuitBreaker.of("orderService", config); // 3. 包装调用 Supplier<String> decorated = CircuitBreaker .decorateSupplier(circuitBreaker, () -> remoteService.call()); // 4. 带降级的调用 try { String result = Try.ofSupplier(decorated) .recover(throwable -> "fallback: service unavailable") .get(); } catch (CallNotPermittedException e) { // 熔断打开时直接走到这里,不会真的调用 remoteService String result = "circuit breaker is OPEN"; }

主流熔断框架对比

框架语言特点适用场景
Resilience4j Java 轻量级、函数式、专为Java8+设计;支持熔断/限流/重试/隔离 Spring Cloud 官方推荐,替代Hystrix
Sentinel Java / Go / C++ 阿里开源、控制台可视化、规则动态下发、支持熔断+限流+降级一体化 国内互联网主流选择,适合复杂治理
Hystrix Java Netflix 出品,线程池隔离 + 信号量隔离,已进入维护模式 老项目维护,新项目不建议使用
Polly .NET .NET 生态标准选择,策略组合灵活 .NET / C# 项目
go-kit/circuitbreaker Go Go 生态的多种熔断器实现(Hystrix-Go、gobreaker等) Go 微服务项目
二、服务降级 Fallback / Degradation
当系统无法提供完整服务时,牺牲非核心功能,保证核心链路可用

降级的本质:丢车保帅

降级是主动的取舍策略。当系统资源紧张时,关闭或简化非核心功能,把资源留给核心链路。这就像飞机遇到气流时,先关掉机上娱乐系统,确保飞行控制系统的电力供应。

降级触发条件
  • CPU / 内存使用率超过阈值
  • 响应时间超过 SLA 上限
  • 下游依赖不可用(触发熔断)
  • 限流触发后对溢出请求降级
  • 大促/秒杀期间主动降级
降级不做什么
  • ❌ 不直接返回 500 错误
  • ❌ 不让用户看到空白页
  • ❌ 不阻塞核心交易链路
  • ✅ 返回缓存/默认值/提示信息
  • ✅ 核心功能必须可用

降级策略分级

级别策略示例用户体验
L1 · 静默 返回缓存数据 首页推荐位读取 Redis 缓存而非实时计算 用户几乎无感知
L2 · 简化 关闭非核心功能 评论功能关闭、个性化推荐改为热门排行 功能减少但核心可用
L3 · 兜底 返回默认/静态数据 用户等级查不到 → 返回"普通会员" 数据可能不准确
L4 · 提示 友好错误提示 支付页面显示"系统繁忙,请稍后再试" 明确告知、不丢失数据

代码实现示例

Java / Sentinel // Sentinel 降级规则 + Fallback 实现 import com.alibaba.csp.sentinel.*; import com.alibaba.csp.sentinel.slots.block.degrade.*; // 1. 定义降级规则(慢调用比例降级) private void initDegradeRule() { DegradeRule rule = new DegradeRule("getUserProfile") .setGrade(RuleConstant.DEGRADE_GRADE_SLOW_REQUEST_RATIO) .setCount(200) // 最大RT 200ms .setSlowRatioThreshold(0.5) // 慢调用比例 > 50% 触发降级 .setMinRequestAmount(10) // 最小请求数 .setStatIntervalMs(1000) // 统计窗口1秒 .setTimeWindow(10); // 降级持续10秒 DegradeRuleManager.loadRules(Collections.singletonList(rule)); } // 2. 带降级兜底的业务方法 @SentinelResource(value = "getUserProfile", fallback = "getUserProfileFallback") public UserProfile getUserProfile(String userId) { // 正常逻辑:查DB + 第三方 + 实时计算 UserProfile profile = dbService.findById(userId); profile.setTags(tagService.computeTags(userId)); // 可能慢 profile.setLevel(vipService.getLevel(userId)); // 可能不可用 return profile; } // 3. 降级兜底方法 public UserProfile getUserProfileFallback(String userId, Throwable e) { // L2简化:只用基础数据 + 缓存 UserProfile profile = cacheService.get(userId); if (profile == null) { profile = UserProfile.builder() .userId(userId) .level("普通会员") // L3兜底:默认值 .tags(Collections.emptyList()) // L3兜底:空列表 .build(); } return profile; }

降级场景矩阵

场景正常返回降级返回降级策略
商品详情-推荐实时个性化推荐热门商品Top 100L2 简化
用户等级查询精确等级"普通会员"L3 兜底
搜索结果完整搜索结果空列表 + 提示L4 提示
评论列表实时评论缓存评论 / 隐藏L1/L2
支付回调查询精确支付状态不能降级!核心链路不降级
三、服务限流 Rate Limiting
控制请求速率,削峰填谷,保证系统在水位线以下运行

四大核心限流算法

以下四种算法是限流的基础,各有适用场景:

🎯 令牌桶算法 — 可视化演示

固定速率生成令牌,请求需获取令牌才能放行。可以应对突发流量(桶内积累的令牌一次性消费)。

桶容量: 20 | 速率: 2/s

四种算法对比

算法原理突发流量平滑性实现复杂度
固定窗口计数器 每个时间窗口(如1s)内计数,超阈值则限流 ✗ 临界问题(窗口边界两倍流量) ★☆☆☆☆
滑动窗口计数器 将窗口细分为多个小格子,滑动统计 △ 缓解临界问题 ★★☆☆☆
漏桶算法 请求进入队列,以固定速率流出处理 ✗ 无法应对突发(强制平滑) ★★★☆☆
令牌桶算法 以固定速率放入令牌,请求消耗令牌 ✓ 支持突发(积攒的令牌可一次消费) ★★★☆☆
临界问题详解:固定窗口计数器在 1s 窗口内限制 100 个请求。但如果在 0.9s~1.0s 来了 100 个请求(第一窗口),1.0s~1.1s 又来了 100 个请求(第二窗口),在 0.9s~1.1s 这 0.2 秒内实际放过了 200 个请求——这就是临界问题。滑动窗口通过细分格子解决此问题。

代码实现示例

Java // Sentinel 流控规则 — 支持 QPS + 线程数两种模式 import com.alibaba.csp.sentinel.slots.block.flow.*; private void initFlowRules() { // QPS 限流:每秒最多 100 个请求 FlowRule rule = new FlowRule("createOrder") .setGrade(RuleConstant.FLOW_GRADE_QPS) // 基于 QPS .setCount(100) // QPS 阈值 .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); FlowRuleManager.loadRules(Collections.singletonList(rule)); } // Sentinel 还支持: // - 线程数限流 (FLOW_GRADE_THREAD):控制并发线程数 // - Warm Up 预热:系统冷启动时逐步放开阈值,避免被瞬间打垮 // - 匀速排队:漏桶模式,请求以均匀速度通过 // - 关联限流:当关联资源达到阈值,限流当前资源 // - 链路限流:只限制入口链路的流量 // 使用 @SentinelResource 注解 @SentinelResource( value = "createOrder", blockHandler = "createOrderBlockHandler" // 限流触发后执行 ) public Order createOrder(OrderRequest req) { return orderService.create(req); } public Order createOrderBlockHandler(OrderRequest req, BlockException e) { throw new BizException("系统繁忙,请稍后再试"); }

限流的实现层级

限流不是只在网关做一层就够了,需要在多个层级协同配合:

层级实现方式粒度适用场景
接入层Nginx / OpenResty / APISIXIP / 域名 / URI防DDoS、防爬虫、全局限流
网关层Spring Cloud Gateway / Kong / Zuul用户 / App / 租户多租户隔离、业务限流
应用层Sentinel / Guava RateLimiter接口 / 方法核心接口保护、热点参数限流
中间件层Redis + Lua 脚本任意维度分布式限流、跨实例协同
四、三者综合对比
放在一起看,理解每个模式的位置和边界

核心差异一览

维度熔断 Circuit Breaker降级 Fallback限流 Rate Limiting
设计模式 断路器模式 兜底 / 后备模式 流量整形模式
作用方向 调用方 → 被调方(切断请求) 被调方 → 调用方(返回兜底) 入口 → 服务(拦截请求)
时间维度 事后响应(已有故障) 事中兜底(正在过载) 事前预防(流量未进入)
决策依据 失败率 / 慢调用率 系统负载 / 依赖状态 QPS / 并发数 / 令牌
恢复方式 自动(冷却 → 半开 → 关闭) 自动(条件消失后恢复) 自动(下一个时间窗口)
对用户的影响 快速失败 + 降级兜底 有损但可用的服务 部分请求被拒绝
典型框架 Resilience4j, Sentinel, Hystrix Sentinel, Hystrix, 业务逻辑 Sentinel, Guava, Nginx, Redis

一图胜千言:请求链路上的位置

🚦 限流层(网关 / Nginx / 应用入口) ✅ 正常调用(通过限流 & 熔断器关闭) 🖥 被调服务(可能触发降级 / 熔断反馈) 降级响应 熔断打开
五、三者如何协同工作
这三种模式不是孤立的,而是互为补充,构成完整的弹性防御体系

协同场景矩阵

组合触发链效果典型场景
限流 → 降级 QPS 超限触发限流 → 对溢出请求执行降级兜底 核心用户不受影响,超量请求获得友好提示 秒杀活动:限量用户正常下单,其余提示"已售罄"
熔断 → 降级 下游服务失败率高触发熔断 → 降级返回缓存/默认数据 调用方不被阻塞,用户仍能看到有用内容 推荐服务挂了 → 返回热门榜单作为兜底
限流 → 熔断 网关限流不足 → 下游被打垮 → 调用方熔断保护自己 多层防御,一层失效后下一层兜底 大促期间:Nginx 限流 → 网关限流 → 应用熔断
限流 + 熔断 + 降级 全链路弹性:限流防入口 → 熔断防级联 → 降级保体验 三重保障,即使部分服务不可用,用户体验不中断 大型电商:双十一等高并发场景的标准配置

工程实践:一个请求的完整生命周期

① 限流检查(Rate Limiter)

请求到达,首先通过限流器。令牌桶/滑动窗口检查当前 QPS 是否超限。超限则返回 429 Too Many Requests,或走降级逻辑。

② 熔断器检查(Circuit Breaker)

通过限流后,检查目标服务的熔断器状态。如果 OPEN,直接快速失败,走降级逻辑(不实际调用下游)。

③ 实际调用

限流和熔断都通过,真正发出RPC调用。记录调用的成功/失败/超时,用于更新熔断器统计。

④ 降级兜底(Fallback)

如果调用失败、超时、被限流或被熔断,执行预先定义好的降级逻辑:返回缓存、默认值、或友好提示。

Sentinel 一体化实现示例

Sentinel 是少数能同时覆盖熔断、降级、限流三个模式的框架,非常适合作为一体化方案。

Java // Sentinel 一体化的熔断 + 降级 + 限流配置 // 1. 流控规则(限流) FlowRule flowRule = new FlowRule("orderService") .setGrade(RuleConstant.FLOW_GRADE_QPS) .setCount(100); // 限制 QPS 100 // 2. 降级规则(熔断) DegradeRule degradeRule = new DegradeRule("orderService") .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) .setCount(0.5) // 异常比例 > 50% 触发 .setMinRequestAmount(10) .setTimeWindow(10); // 熔断 10 秒 FlowRuleManager.loadRules(Arrays.asList(flowRule)); DegradeRuleManager.loadRules(Arrays.asList(degradeRule)); // 3. 业务代码:blockHandler(限流) + fallback(降级/熔断) @SentinelResource( value = "orderService", blockHandler = "handleFlowLimit", // 限流触发 fallback = "handleFallback" // 熔断/异常触发 ) public Order createOrder(OrderRequest req) { return orderService.create(req); } // 限流处理:返回友好错误 public Order handleFlowLimit(OrderRequest req, BlockException e) { throw new BizException("系统繁忙,请稍后再试"); } // 降级处理:返回兜底数据 public Order handleFallback(OrderRequest req, Throwable e) { return Order.builder() .status("PENDING") .message("订单处理中,请稍后查看") .build(); }

框架选型建议

场景推荐方案理由
Java 微服务(新项目) Sentinel 熔断+降级+限流一体化,可视化控制台,阿里大规模验证
Java 微服务(小团队) Resilience4j 轻量、函数式风格、Spring Cloud 官方推荐
Go 微服务 Sentinel-Go + 自研熔断器 Sentinel 有 Go SDK,也可用 gobreaker 等轻量库
Python 微服务 pybreaker + 自研令牌桶 Python 生态轻量库组合,令牌桶实现简单
网关层限流 Nginx / APISIX / Kong 接入层统一限流,性能最高,运维成熟
分布式限流 Redis + Lua 原子操作保证精确,跨实例共享配额