3、常见限流算法详解(下):漏桶算法原理、令牌桶算法原理、四种算法适用场景对比表
在上一节中,我们深入剖析了计数器算法与滑动窗口算法的原理与边界问题。本节将重点讲解微服务网关中最常用的两种“桶”算法——漏桶算法与令牌桶算法,并在最后给出四种算法的适用场景对比表,帮助你在实际调优中快速选型。
3.1 漏桶算法(Leaky Bucket)原理
漏桶算法的核心思想是将突发请求流“削峰填谷”,强制以恒定速率处理请求。无论上游流量如何波动,经过漏桶后,下游服务看到的始终是平滑的请求流。
3.1.1 核心机制
- 桶容量(Capacity):桶的最大容量,对应允许的最大突发请求数。超出容量的请求直接丢弃(或排队失败)。
- 漏水速率(Leak Rate):桶底部漏水的固定速率,即单位时间内从桶中取出并处理的请求数。
- 当前水位(Water Level):桶中当前积压的请求数。
当请求到达时,若桶未满则放入桶中;若桶已满则拒绝。桶底以恒定速率“漏水”处理请求,不受上游突发影响。
3.1.2 漏桶算法工作流程
- 请求到达网关,检查当前桶中水位是否小于桶容量。
- 若水位 < 容量,请求入桶,水位 +1;否则请求被限流(丢弃或返回 429)。
- 后台定时器以固定速率从桶底取出请求,交给下游服务处理,水位 -1。
关键特性:漏桶算法的输出速率绝对平滑,适合需要严格保护下游数据库或单线程资源的场景。但缺点是无法应对突发流量——即使下游有能力处理更多请求,漏桶也不会加速。
3.1.3 漏桶算法内联 SVG 流程图
3.2 令牌桶算法(Token Bucket)原理
令牌桶算法是目前 API 网关(如 Kong、Spring Cloud Gateway、Envoy)中使用最广泛的限流算法。它允许一定程度的突发流量,同时保证长期平均速率可控。
3.2.1 核心机制
- 桶容量(Capacity):桶中最多存放的令牌数,决定了最大突发请求量。
- 令牌生成速率(Token Rate):系统以固定速率向桶中添加令牌,单位通常是 个/秒。
- 当前令牌数(Tokens):桶中当前可用的令牌数量。
每个请求到达时,必须从桶中获取一个(或多个)令牌才能通过。如果桶中有足够令牌,请求立即放行;否则请求被限流。令牌生成是持续的,即使桶满也不再增加。
3.2.2 令牌桶算法工作流程
- 后台定时器以固定速率向桶中添加令牌,桶满则停止。
- 请求到达网关,检查桶中令牌数是否 ≥ 请求所需令牌数(通常为 1)。
- 若令牌充足,从桶中取出令牌,请求放行;否则请求被限流。
调优要点:令牌桶的“桶容量”参数直接控制突发能力。例如,设置令牌生成速率为 100 req/s,桶容量为 200,则允许瞬间 200 个请求并发通过,但长期平均速率仍为 100 req/s。这在应对秒杀、热点新闻等场景时非常有效。
3.2.3 令牌桶算法内联 SVG 流程图
3.3 四种算法适用场景对比表
为了帮助你根据业务场景快速选择最合适的限流算法,下表从突发处理能力、输出平滑度、实现复杂度、典型应用四个维度进行对比。
| 算法 | 突发处理能力 | 输出平滑度 | 实现复杂度 | 典型应用场景 |
|---|---|---|---|---|
| 计数器算法 | 弱(窗口边界易突刺) | 低(临界突变) | 最低 | 简单接口限流、非关键路径、Demo 环境 |
| 滑动窗口算法 | 中等(窗口内可突发) | 中(粒度取决于子窗口数) | 中 | 通用 API 限流、需要避免边界突刺的场景 |
| 漏桶算法 | 弱(仅桶容量内可突发) | 最高(绝对平滑) | 中 | 数据库连接池保护、下游单线程处理、消息队列消费速率控制 |
| 令牌桶算法 | 强(桶容量决定突发上限) | 高(长期平滑,允许短时突发) | 中高 | API 网关限流、微服务入口、秒杀/抢购、流量整形 |
选型建议:在微服务 API 网关场景中,令牌桶算法是首选。它既能通过桶容量应对突发流量,又能通过令牌生成速率保证长期平均负载可控。漏桶算法更适合下游处理能力严格固定的场景(如写入 HBase 或单线程日志处理)。计数器算法和滑动窗口算法实现简单,但突发控制能力较弱,适合非关键路径或早期快速迭代阶段。
3.4 四种算法核心参数速查
下表汇总了每种算法在网关配置中需要关注的核心参数,方便你在调优时快速定位。
| 算法 | 核心参数 | 参数说明 | 调优方向 |
|---|---|---|---|
| 计数器 | limit, window_size | 窗口内最大请求数、窗口时长(秒) | 增大窗口时长可平滑流量,但延迟增加 |
| 滑动窗口 | limit, window_size, sub_window_count | 窗口内最大请求数、窗口时长、子窗口数量 | 子窗口越多精度越高,但内存开销增大 |
| 漏桶 | capacity, leak_rate | 桶容量、漏水速率(请求/秒) | 容量决定容忍突发量,速率决定下游负载 |
| 令牌桶 | capacity, token_rate | 桶容量、令牌生成速率(令牌/秒) | 容量控制突发上限,速率控制长期 QPS |