2. 限流算法基础
限流算法是模型验证 API 抵御突发流量、保障后端推理服务稳定的第一道防线。不同的算法在突发处理能力、平滑度与实现复杂度上各有取舍。本章深入剖析四种核心算法的原理与适用场景。
2.1 令牌桶算法
令牌桶算法是业界最通用的限流方案,允许一定程度的突发流量,同时限制长期平均速率。
- 核心机制:系统以固定速率向桶中放入令牌,每个请求需消耗一个令牌才能被处理。桶有最大容量,超出部分令牌丢弃。
- 突发处理:当桶中积累令牌时,可一次性处理多个请求,实现突发响应。
- 适用场景:允许短时流量尖峰、需要平滑长期速率的 API 网关。
关键参数:令牌填充速率
r(个/秒)、桶容量 b(个)。最大突发请求数 = b,持续突发时长 = b / (r - 实际流入速率)。
2.2 漏桶算法
漏桶算法将请求视为水滴,以固定速率从桶底漏出,强制输出完全平滑,不允许突发。
- 核心机制:请求进入桶中排队,桶底以恒定速率处理请求。桶满时新请求被丢弃。
- 平滑性:无论入口流量多剧烈,出口流量始终均匀,适合保护下游脆弱系统。
- 适用场景:数据库写入、消息队列消费、对抖动敏感的模型推理服务。
注意:漏桶算法无法利用空闲资源处理突发请求,可能导致大量请求被拒,而下游资源却处于空闲状态。
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 的限流配置中,推荐以下选型策略:
- 默认首选:令牌桶算法,兼顾突发处理与长期速率控制,适合大多数推理场景。
- 严格平滑:漏桶算法,适用于对延迟抖动敏感的模型服务。
- 精确控制:滑动窗口算法,适用于需要严格限制窗口内请求总数的场景。
- 避免使用:纯计数器算法,临界问题可能导致限流失效,不建议在生产环境使用。
重要:无论选择哪种算法,都应结合熔断机制形成完整防护。限流控制请求速率,熔断在错误率过高时快速切断流量,两者互补才能保障系统稳定。