2. 限流算法基础

限流算法是模型验证 API 抵御突发流量、保障后端推理服务稳定的第一道防线。不同的算法在突发处理能力、平滑度与实现复杂度上各有取舍。本章深入剖析四种核心算法的原理与适用场景。

2.1 令牌桶算法

令牌桶算法是业界最通用的限流方案,允许一定程度的突发流量,同时限制长期平均速率。

  • 核心机制:系统以固定速率向桶中放入令牌,每个请求需消耗一个令牌才能被处理。桶有最大容量,超出部分令牌丢弃。
  • 突发处理:当桶中积累令牌时,可一次性处理多个请求,实现突发响应。
  • 适用场景:允许短时流量尖峰、需要平滑长期速率的 API 网关。
关键参数:令牌填充速率 r(个/秒)、桶容量 b(个)。最大突发请求数 = b,持续突发时长 = b / (r - 实际流入速率)。
令牌桶算法原理 令牌生成器 速率 r 个/秒 令牌桶 容量 b 已存令牌数 (动态变化) 请求到达 有令牌? 处理请求 拒绝请求 令牌桶允许突发:桶满时可一次性消耗所有令牌,处理大量请求 长期平均速率 = 令牌填充速率 r

2.2 漏桶算法

漏桶算法将请求视为水滴,以固定速率从桶底漏出,强制输出完全平滑,不允许突发。

  • 核心机制:请求进入桶中排队,桶底以恒定速率处理请求。桶满时新请求被丢弃。
  • 平滑性:无论入口流量多剧烈,出口流量始终均匀,适合保护下游脆弱系统。
  • 适用场景:数据库写入、消息队列消费、对抖动敏感的模型推理服务。
注意:漏桶算法无法利用空闲资源处理突发请求,可能导致大量请求被拒,而下游资源却处于空闲状态。
漏桶算法原理 请求流入 漏桶 请求队列 (FIFO) 桶容量有限 恒定速率漏出 处理请求 桶满丢弃 漏桶强制输出平滑:出口速率恒定,不随入口流量波动 无法利用空闲资源处理突发,适合保护脆弱下游

2.3 计数器算法

计数器算法是最直观的限流实现,在固定时间窗口内统计请求总数,超过阈值则拒绝。

  • 核心机制:将时间划分为固定窗口(如 1 秒),每个窗口维护一个计数器。请求到达时计数器加 1,超过阈值则拒绝。
  • 临界问题:窗口切换瞬间可能出现双倍流量峰值,导致限流失效。
  • 适用场景:对精度要求不高、实现简单的轻量级限流。
临界问题示例:限流阈值 100 次/秒。第 1 秒最后 100ms 处理 100 个请求,第 2 秒前 100ms 又处理 100 个请求。实际 200ms 内处理了 200 个请求,远超阈值。

2.4 滑动窗口算法

滑动窗口算法是计数器算法的改进版本,通过细粒度子窗口解决临界问题,实现更平滑的限流。

  • 核心机制:将时间窗口划分为多个子窗口(如 1 秒窗口分为 10 个 100ms 子窗口)。滑动时丢弃过期子窗口数据,统计当前窗口内所有子窗口的请求总和。
  • 精度控制:子窗口数量越多,精度越高,但内存开销也越大。
  • 适用场景:需要精确限流、防止突发穿透的生产环境 API 网关。
实践建议:滑动窗口子窗口数量通常设为 10~20 个,可在精度与性能之间取得平衡。对于模型验证 API,建议使用 10 个子窗口(每 100ms 一个)。

2.5 算法对比

算法 突发处理 输出平滑度 实现复杂度 内存开销 典型场景
令牌桶 支持突发 中等 中等 低 API 网关、Web 服务
漏桶 不支持 最高 低 低 数据库写入、消息队列
计数器 有临界问题 低 最低 最低 简单限流、测试环境
滑动窗口 精确控制 高 较高 中等 生产环境精确限流

2.6 选型建议

在模型验证 API 的限流配置中,推荐以下选型策略:

  • 默认首选:令牌桶算法,兼顾突发处理与长期速率控制,适合大多数推理场景。
  • 严格平滑:漏桶算法,适用于对延迟抖动敏感的模型服务。
  • 精确控制:滑动窗口算法,适用于需要严格限制窗口内请求总数的场景。
  • 避免使用:纯计数器算法,临界问题可能导致限流失效,不建议在生产环境使用。
重要:无论选择哪种算法,都应结合熔断机制形成完整防护。限流控制请求速率,熔断在错误率过高时快速切断流量,两者互补才能保障系统稳定。