4. 限流与熔断基础概念
在分布式系统与微服务架构中,限流(Rate Limiting)与熔断(Circuit Breaker)是保障服务稳定性的两大核心手段。二者常被混淆,但职责、触发机制与治理粒度截然不同。本节从定义出发,通过对比表格与流程图示,厘清它们的区别与协同关系。
4.1 限流(Rate Limiting)
定义:限流是一种主动预防策略,通过控制单位时间内允许通过的请求数量,防止系统被突发流量冲垮。它作用于请求入口,在流量到达业务逻辑之前进行拦截。
- 核心目标:保护后端资源(CPU、内存、数据库连接池)不被过度使用。
- 常见算法:令牌桶(Token Bucket)、漏桶(Leaky Bucket)、滑动窗口(Sliding Window)、计数器(Fixed Window)。
- 触发条件:基于请求速率(QPS/TPS)或并发数。
- 响应行为:直接拒绝(返回 429 Too Many Requests)、排队等待、降级响应。
实践提示:在 NestJS 中,限流通常通过守卫(Guard)或拦截器(Interceptor)在 Controller 层实现,配合 @nestjs/throttler 模块或自定义中间件。
4.2 熔断(Circuit Breaker)
定义:熔断是一种被动恢复策略,通过监控下游服务(或依赖资源)的调用失败率,当失败率达到阈值时自动断开链路,避免级联故障(Cascading Failure)。它作用于服务调用出口,在调用远程服务时进行保护。
- 核心目标:防止故障扩散,给下游服务恢复时间。
- 常见状态机:关闭(Closed)→ 打开(Open)→ 半开(Half-Open)。
- 触发条件:基于失败率(如 50% 请求失败)、慢调用比例或异常计数。
- 响应行为:快速失败(返回 Fallback 响应)、抛出异常、静默降级。
关键区别:限流是主动控制流量速率,熔断是被动响应故障状态。限流保护的是自身,熔断保护的是依赖链。
4.3 核心区别对比
| 维度 | 限流(Rate Limiting) | 熔断(Circuit Breaker) |
|---|---|---|
| 控制方向 | 入口流量控制(Ingress) | 出口调用控制(Egress) |
| 触发依据 | 请求速率 / 并发数 | 失败率 / 慢调用比例 |
| 状态模型 | 无状态(计数器/桶) | 有状态(Closed/Open/Half-Open) |
| 恢复方式 | 时间窗口重置(自动恢复) | 超时后尝试半开探测 |
| 典型错误码 | 429 Too Many Requests | 503 Service Unavailable / Fallback |
| 治理粒度 | API 端点 / 用户 / IP | 远程服务 / 资源依赖 |
4.4 协同关系:限流 + 熔断的互补模型
在实际系统中,限流与熔断并非二选一,而是形成双层防护:
- 第一层(入口层):限流拦截突发流量,保护自身不被压垮。
- 第二层(出口层):熔断监控下游健康状态,防止调用链雪崩。
当限流触发时,熔断可能尚未感知;当熔断打开时,限流仍在正常运作——二者独立运行,但共同降低系统整体风险。
4.5 典型场景对比
| 场景 | 适用策略 | 原因 |
|---|---|---|
| 秒杀活动、突发流量 | 限流 | 流量瞬间暴增,需主动削峰 |
| 数据库连接池耗尽 | 限流 | 控制并发连接数,防止资源枯竭 |
| 下游服务响应超时 | 熔断 | 避免等待堆积,快速失败 |
| 下游服务连续报错 | 熔断 | 切断故障链路,防止雪崩 |
| API 被恶意刷单 | 限流 + 熔断 | 限流拦截高频请求,熔断保护下游 |
4.6 在 NestJS 中的落地位置
- 限流:通常放在 Guard 或 Interceptor 中,在 Controller 方法执行前检查速率。NestJS 官方推荐
@nestjs/throttler模块。 - 熔断:通常放在 Service 层 或 自定义 Provider 中,包裹对外部服务的 HTTP 调用(如使用 Axios、HttpService)。可借助
opossum库实现状态机。
架构原则:限流靠近入口(Controller),熔断靠近出口(Service/Client Proxy)。二者在 NestJS 模块中可独立配置,互不干扰。
4.7 小结
- 限流是事前控制,熔断是事中恢复。
- 二者在 NestJS 中可分别通过
@nestjs/throttler和opossum实现,互不冲突。 - 协同使用时,限流降低熔断触发概率,熔断兜底限流无法处理的依赖故障。