2. Rate Limiting 基础概念:限流算法概述与常见应用场景
限流(Rate Limiting)是分布式系统与 API 网关中控制流量进入速率的核心手段。其本质是在单位时间内限制请求数量,防止系统过载、资源耗尽或遭受恶意攻击。本节将系统梳理三种主流限流算法及其典型应用场景,为后续参数配置与缓存一致性测试奠定理论基础。
2.1 三大限流算法对比
| 算法 | 核心思想 | 流量特征 | 突发处理 | 适用场景 |
|---|---|---|---|---|
| 令牌桶 | 以固定速率向桶内投放令牌,请求需获取令牌才能通过 | 允许一定程度的突发流量 | 支持(桶内令牌积累) | API 限流、微服务网关 |
| 漏桶 | 请求以固定速率从桶底漏出,超出桶容量的请求被丢弃 | 强制平滑,严格整形 | 不支持 | 流量整形、网络 QoS |
| 滑动窗口 | 将时间划分为小窗口,统计窗口内请求数,窗口随时间滑动 | 接近实时,边界精度高 | 受窗口粒度限制 | 防刷、秒杀、计数器 |
选型提示: 令牌桶是业界最通用的限流算法,兼顾平均速率与突发能力;漏桶适合需要严格削峰填谷的场景;滑动窗口在分布式计数器与防刷场景中精度优于固定窗口。
2.2 令牌桶算法(Token Bucket)
令牌桶算法通过两个参数控制流量:桶容量(burst) 和 令牌生成速率(rate)。系统以恒定速率向桶中添加令牌,每个请求消耗一个令牌;若桶中令牌不足,请求被拒绝或等待。桶容量决定了允许的最大突发请求数。
2.3 漏桶算法(Leaky Bucket)
漏桶算法将请求视为水滴,以恒定速率从桶底漏出。桶容量固定,当桶满时新请求被丢弃。漏桶强制输出流量完全平滑,适合需要严格整形流量的场景,如网络 QoS 和数据库写入限流。
漏桶 vs 令牌桶核心区别: 漏桶的输出速率恒定,无法应对突发;令牌桶允许短时突发,但平均速率受控。漏桶更适用于下游处理能力固定的系统,令牌桶更适用于需要弹性响应的 API 网关。
2.4 滑动窗口算法(Sliding Window)
滑动窗口算法将时间轴划分为多个小窗口(如 1 秒),每个窗口维护一个计数器。窗口随时间向前滑动,过期窗口的计数被丢弃。当前总请求数为所有活跃窗口计数之和。相比固定窗口,滑动窗口避免了边界突刺问题。
2.5 常见应用场景
| 场景 | 推荐算法 | 典型配置 | 说明 |
|---|---|---|---|
| API 限流 | 令牌桶 | rate=100 req/s, burst=200 | 允许短时突发,保障 API 响应弹性 |
| 防刷(DDoS/爬虫) | 滑动窗口 | 窗口=1s, 阈值=50 | 细粒度检测异常高频请求,快速阻断 |
| 流量整形 | 漏桶 | 漏出速率=50 req/s, 桶深=100 | 强制输出平滑,保护下游脆弱系统 |
| 秒杀/抢购 | 滑动窗口 + 令牌桶 | 窗口=100ms, 阈值=10 | 组合使用,兼顾精度与突发处理 |
| 数据库连接池限流 | 漏桶 | 漏出速率=10 conn/s | 防止连接池被瞬时打满 |
常见误区: 固定窗口算法(如每分钟重置计数器)在窗口边界处容易出现流量突刺——请求在窗口末尾和下一窗口开头集中涌入,导致瞬时 QPS 翻倍。滑动窗口通过分片滑动有效缓解此问题,但会引入额外的内存与计算开销。
2.6 算法选型决策树
在实际项目中,算法选型需结合业务容忍度与系统资源。以下决策路径可供参考:
- 是否需要严格平滑输出? → 是 → 选择漏桶算法
- 是否需要应对突发流量? → 是 → 选择令牌桶算法
- 是否需要高精度边界控制? → 是 → 选择滑动窗口算法
- 场景复杂,需要组合策略? → 是 → 令牌桶 + 滑动窗口双层限流