3、常见限流算法详解(下):漏桶算法原理、令牌桶算法原理、四种算法适用场景对比表

在上一节中,我们深入剖析了计数器算法与滑动窗口算法的原理与边界问题。本节将重点讲解微服务网关中最常用的两种“桶”算法——漏桶算法与令牌桶算法,并在最后给出四种算法的适用场景对比表,帮助你在实际调优中快速选型。

3.1 漏桶算法(Leaky Bucket)原理

漏桶算法的核心思想是将突发请求流“削峰填谷”,强制以恒定速率处理请求。无论上游流量如何波动,经过漏桶后,下游服务看到的始终是平滑的请求流。

3.1.1 核心机制

  • 桶容量(Capacity):桶的最大容量,对应允许的最大突发请求数。超出容量的请求直接丢弃(或排队失败)。
  • 漏水速率(Leak Rate):桶底部漏水的固定速率,即单位时间内从桶中取出并处理的请求数。
  • 当前水位(Water Level):桶中当前积压的请求数。

当请求到达时,若桶未满则放入桶中;若桶已满则拒绝。桶底以恒定速率“漏水”处理请求,不受上游突发影响。

3.1.2 漏桶算法工作流程

  1. 请求到达网关,检查当前桶中水位是否小于桶容量。
  2. 若水位 < 容量,请求入桶,水位 +1;否则请求被限流(丢弃或返回 429)。
  3. 后台定时器以固定速率从桶底取出请求,交给下游服务处理,水位 -1。
关键特性:漏桶算法的输出速率绝对平滑,适合需要严格保护下游数据库或单线程资源的场景。但缺点是无法应对突发流量——即使下游有能力处理更多请求,漏桶也不会加速。

3.1.3 漏桶算法内联 SVG 流程图

漏桶算法工作流程 请求到达 桶是否已满? 丢弃请求 请求入桶(水位+1) 桶(容量固定) 固定速率漏水

3.2 令牌桶算法(Token Bucket)原理

令牌桶算法是目前 API 网关(如 Kong、Spring Cloud Gateway、Envoy)中使用最广泛的限流算法。它允许一定程度的突发流量,同时保证长期平均速率可控。

3.2.1 核心机制

  • 桶容量(Capacity):桶中最多存放的令牌数,决定了最大突发请求量。
  • 令牌生成速率(Token Rate):系统以固定速率向桶中添加令牌,单位通常是 个/秒。
  • 当前令牌数(Tokens):桶中当前可用的令牌数量。

每个请求到达时,必须从桶中获取一个(或多个)令牌才能通过。如果桶中有足够令牌,请求立即放行;否则请求被限流。令牌生成是持续的,即使桶满也不再增加。

3.2.2 令牌桶算法工作流程

  1. 后台定时器以固定速率向桶中添加令牌,桶满则停止。
  2. 请求到达网关,检查桶中令牌数是否 ≥ 请求所需令牌数(通常为 1)。
  3. 若令牌充足,从桶中取出令牌,请求放行;否则请求被限流。
调优要点:令牌桶的“桶容量”参数直接控制突发能力。例如,设置令牌生成速率为 100 req/s,桶容量为 200,则允许瞬间 200 个请求并发通过,但长期平均速率仍为 100 req/s。这在应对秒杀、热点新闻等场景时非常有效。

3.2.3 令牌桶算法内联 SVG 流程图

令牌桶算法工作流程 令牌生成器 令牌桶(容量N) 请求到达 令牌数 ≥ 所需? 放行(令牌-1) 限流(拒绝请求)

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