2. 限流基础概念:令牌桶、漏桶、计数器算法的原理与对比

在模型发布场景中,API 网关或推理服务必须应对突发流量、恶意爬虫以及后端资源瓶颈。限流(Rate Limiting)是保护系统不被瞬时洪峰冲垮的第一道防线。本章深入剖析三种最经典的限流算法——令牌桶、漏桶和计数器,从原理、实现到适用场景进行系统对比。

2.1 令牌桶算法(Token Bucket)

令牌桶是目前工业界应用最广泛的限流算法,也是 API Gateway 和 模型推理服务 的首选方案。其核心思想是:系统以恒定速率向桶中放入令牌,每个请求必须获取一个令牌才能被处理;桶有容量上限,允许一定程度的突发流量。

关键参数:
  • r(rate):令牌生成速率,即平均每秒放入桶中的令牌数。
  • b(burst):桶的最大容量,即允许的瞬时突发请求数。
  • 当桶满时,新生成的令牌被丢弃;当桶空时,请求被拒绝或排队等待。
令牌桶算法原理图 令牌生成器 速率 r 个/秒 恒定速率 令牌桶 容量 b 令牌(最多 b 个) 取令牌 请求处理 通过 请求到达 拒绝/排队
模型发布场景建议: 令牌桶算法非常适合处理 LLM 推理服务的突发请求。例如,设置 r=10(每秒 10 个请求)、b=20(允许瞬间 20 个并发),既能保证长期平均速率,又能容忍用户短时间内的密集调用。

2.2 漏桶算法(Leaky Bucket)

漏桶算法与令牌桶相反,它强制请求以恒定速率流出,无论流入速率多快。漏桶像一个底部有漏洞的水桶,水(请求)以固定速率漏出,桶满则溢出(拒绝请求)。

漏桶算法原理图 请求流入 任意速率 流入 漏桶 容量 b 请求队列(先进先出) 漏洞 恒定流出 速率 r 个/秒 溢出丢弃 桶满时
注意: 漏桶算法严格平滑流量,不允许任何突发。对于模型推理服务,如果用户突然发送一批请求,漏桶会强制排队以恒定速率处理,可能导致高延迟。因此漏桶更适合流量整形场景,而非需要容忍突发的模型 API。

2.3 计数器算法(Counter / Fixed Window)

计数器算法是最直观的限流方式:在固定时间窗口(如 1 秒、1 分钟)内统计请求总数,超过阈值则拒绝后续请求。窗口结束后计数器重置。

常见实现方式:
  • 固定窗口计数器: 每个窗口独立计数,窗口切换时瞬间重置。
  • 滑动窗口计数器: 将窗口细分为多个小格,滑动统计,精度更高。
# 固定窗口计数器示例(Python)
import time

class FixedWindowCounter:
    def __init__(self, limit: int, window_sec: int = 1):
        self.limit = limit
        self.window_sec = window_sec
        self.counter = 0
        self.window_start = time.time()

    def allow(self) -> bool:
        now = time.time()
        if now - self.window_start >= self.window_sec:
            # 新窗口,重置
            self.window_start = now
            self.counter = 0
        if self.counter < self.limit:
            self.counter += 1
            return True
        return False
固定窗口的临界问题: 假设限制 100 次/秒。如果在第 0.9 秒时累计 100 次,第 1.0 秒窗口重置,第 1.1 秒又累计 100 次。实际上 0.2 秒内通过了 200 次请求,形成流量毛刺。滑动窗口算法通过细粒度分格缓解此问题,但无法完全消除。

2.4 三种算法对比

维度 令牌桶 漏桶 计数器(固定窗口)
核心机制 恒定速率放令牌,请求取令牌 请求入桶,恒定速率漏出 固定窗口内计数,超限拒绝
突发处理 允许突发(桶容量内) 不允许突发,严格平滑 允许窗口内突发,但窗口边界有毛刺
流量整形 中等(允许一定波动) 强(完全平滑) 弱(窗口内可集中)
实现复杂度 中等(需定时器或延迟计算) 中等(需队列 + 定时器) 低(仅计数 + 时间判断)
内存开销 低(仅维护桶状态) 中(需队列存储等待请求) 极低(仅一个计数器)
适用场景 API 网关、模型推理、微服务 网络流量整形、数据库写入限流 简单限流、IP 黑名单、测试环境
模型发布推荐度 ★★★★★ ★★★☆☆ ★★☆☆☆

2.5 模型发布场景选型建议

  • 首选令牌桶: 模型推理服务通常需要容忍用户突发请求(如批量测试、并发调用),令牌桶的 burst 能力天然匹配。
  • 慎用漏桶: 如果模型服务对延迟极度敏感(如实时语音交互),漏桶的排队机制可能引入不可接受的等待。
  • 计数器仅用于兜底: 在全局 IP 级别做粗粒度限制时,计数器实现简单、性能高,但不要作为核心限流策略。
实战经验: 在 Kubernetes 部署的模型推理服务中,通常使用 令牌桶 + 滑动窗口 的组合策略。令牌桶控制平均速率和突发,滑动窗口在秒级粒度上做二次校验,防止令牌桶在极端情况下(如时钟偏差)产生毛刺。