限流(Rate Limiting)
LLM 调用的限流不是 RPM 一个数字 —— 它是 4 种计量、5 层叠加、4 种算法、5 种触发后行为的组合策略
很多团队第一次接触 LLM 网关时,会以为限流就是「每分钟最多多少次请求」。当真正跑到生产、遇到下面这些场景时才会发现远不止:
- 一个 100k 上下文的请求一次性就能烧掉整个 TPM 上限。
- 流式响应延迟 60 秒返回,期间一直在消耗 token,怎么计算?
- 平台总共 10k RPM,但希望每个客户只能用 100 RPM。
- VIP 客户希望限流松一些 —— 而不是另一套独立部署。
- 限流触发了,到底应该 429 拒绝、排队、还是降级到便宜模型?
- 月底成本超标想立刻刹车,但又不希望误伤正在跑的批任务。
Hydite Vtslx AO 的限流系统就是为了把上面这些问题一站式解决。本文是一份完整的决策手册,读完你应该能回答四个问题:
- 你的场景属于哪一类限流?
- 选哪种计量单位与算法?
- 在 Org / Group / Key / User 哪一层配置?
- 限流被触发时怎么排查 / 怎么恢复?
1. 四种计量单位#
LLM 网关不能只看请求数。Hydite 同时支持四种计量单位,可单独使用也可组合叠加:
| 计量 | 度量目标 | 适用 | 典型值 |
|---|---|---|---|
| RPM(Requests Per Minute) | 请求次数 | 防爬虫 / 防滥用 / 限制并发风险 | 60 ~ 100,000 |
| TPM(Tokens Per Minute) | prompt + completion token 总量 | 真正限制算力消耗 | 10k ~ 100M |
| Concurrency | 同时进行的请求数 | 防止长上下文请求堆积 | 1 ~ 1,000 |
| Budget | 月 / 日累计美元消费 | 防止账单失控 | $1 ~ $1M+ |
核心建议:
- 必配 TPM:RPM 是表象,TPM 才是 LLM 网关的「真硬币」。一个 200k 上下文的请求 1 次就 = 普通请求 200 次。
- 辅以 RPM:用作"高频小请求"场景的兜底。
- 加上 Concurrency 控制长上下文 / 流式请求的堆积:流式调用占用连接很久,一旦并发数 100+,下游 GPU 排队会崩。
- Budget 是终极保险丝:硬上限到点立刻停(hard),软上限只发告警(soft)。
2. 五层继承架构#
1Organization ←— 顶层红线(合同上限、安全合规)2 │3 Group ←— 业务边界(按场景 / 客户 / 环境分)4 │5 Team ←— 人员单位(同一组人共享配额)6 │7 Key ←— 单凭证(前端 / 后端 / CI / 演示)8 │9 end-user-id ←— SaaS 终端用户(防止单用户拖累整体)生效顺序:每一层都计算独立计数器,请求必须同时通过所有层,否则被最严格的那层拦截。
举个真实例子:
| 层级 | RPM 上限 |
|---|---|
| Org | 100,000 |
Group: prod-api | 60,000 |
Team: growth-team | 10,000 |
Key: frontend-web | 1,000 |
end-user user_42 | 30 |
user_42 真正能跑的速率 = min(100,000, 60,000, 10,000, 1,000, 30) = 30 RPM。
这给运营带来三个关键能力:
- 安全团队 在 Org 设兜底,业务团队 在 Group 调灵活,开发 在 Key 做最后微调,互不打架。
- 无需独立部署 VIP 客户的环境:把 VIP 单独放进一个高配额 Group 即可。
- 精细排查:限流被触发时,响应里会标注是哪一层击中了限流,10 秒定位问题。
3. 四种算法 —— 怎么选#
| 算法 | 准确度 | 突发容忍 | 性能开销 | 适用 |
|---|---|---|---|---|
| Sliding Window | ★★★★★ | ★★ | 中 | 默认推荐;高准确度 + 公平 |
| Token Bucket | ★★★★ | ★★★★★ | 低 | 客户端有自然抖动、希望容忍短时突发 |
| Leaky Bucket | ★★★ | ★★★ | 低 | 希望平滑输出(典型:异步爬虫、爆款活动) |
| Fixed Window | ★★ | ★ | 极低 | 历史兼容、对边界突刺不敏感 |
何时偏离默认:
- 客户都是后台 batch(爆量但稳定)→ Token Bucket,给 50% 突发容忍。
- 业务流量和上游 GPU 都怕浪涌 → Leaky Bucket,硬性平滑。
- 老 SDK 期望分钟整点重置 → Fixed Window。
- 其它情况一律用 Sliding Window。
控制台 → Channels → Group Settings → Rate Limiting Algorithm 一键切换,无需重启。
4. 五种触发后的行为#
限流被打中,直接 429 是最简单的,但很多场景下并不是最优解:
| 行为 | 客户体验 | 适用 |
|---|---|---|
| Reject (429) | 立即失败 + Retry-After | 实时交互场景,让客户端自己退避 |
| Queue | 请求排队等下一个时间窗口 | 后台批处理、异步任务(最大延迟 60s) |
| Fallback | 自动切换到便宜 / 备份模型 | 高优先级业务不能 429,但可以容忍模型降级 |
| Soft Limit | 不阻断,只触发 Webhook 告警 | 预算预警、巡检 |
| Burst | 短时段 Burst Pool 允许突破 | 营销活动开抢、闪电交易 |
Queue 和 Fallback 是 Hydite 的差异化能力:
- Queue 模式:限流触发时不抛错,Hydite 把请求放进有限大小的内置队列,等下一个滑动窗口到了直接放行 —— 客户端只感觉延迟略高。
- Fallback 模式:与 Group 的路由策略联动,比如主路
claude-sonnet-4-5满了,Fallback 到claude-3-5-sonnet,再不行降到gpt-4o-mini,保证业务不掉。
可以在 Group / Key 上分别配置。比如同一个 Group 里:
key-frontend→ Reject(前端用户应能感知失败并重试)key-batch→ Queue(后台批处理可等)key-vip→ Fallback(VIP 永不报错)
5. 六个真实业务剧本#
5.1 防爬虫但不误伤真实用户#
不要只看 RPM。爬虫真正暴露自己的点是行为模式:
1group: public-website2quota:3 rpm: 100 # 单 IP 每分钟最多 1004 tpm: 50_0005 concurrency: 56end_user_limit:7 rpm: 30 # 同一 end-user-id 进一步压到 308network:9 ip_rate_limit: 60 # 单 IP 每分钟超 60 强制 captcha10on_exceed: reject加上 Origin 校验和 mTLS(详见 API Key Groups · 网络),爬虫基本无所遁形。
5.2 SaaS 多租户#
你的产品上有 1000 个客户,希望每个客户最多 100 RPM、整体不超 50k RPM:
1group: saas-customers2quota:3 rpm: 50_000 # 整体总闸4 tpm: 10_000_0005end_user_limit: # 关键:以 end-user-id 为单位6 rpm: 1007 tpm: 200_0008on_exceed: reject业务侧只需在请求里带上 metadata.user_id:
1client.chat.completions.create(2 model="claude-sonnet-4-5",3 messages=[...],4 extra_body={"metadata": {"user_id": "customer_42"}},5)Hydite 自动按 customer_42 单独计数。不需要为每个客户签 Key、不需要任何额外代码。
5.3 前端 / 后端共用 Group 但隔离爆炸#
1Group: prod-api (60k RPM)2├─ Key: frontend-web → 限制 RPM 5k, TPM 1M, 仅可见便宜模型3├─ Key: backend-batch → 限制 RPM 30k, TPM 5M, 全部模型, Queue mode4└─ Key: ci-bot → 限制 RPM 100, 单日预算 $20前端被 DDoS 压不垮 backend 的 batch 任务;CI bot 不会因脚本 bug 烧光预算。
5.4 VIP 客户更宽松#
不需要为 VIP 单独部署一套。新建一个 Group:
1group: vip-tier-platinum2quota:3 rpm: 10_000 # VIP 普通版的 10x4 tpm: 5_000_0005on_exceed: fallback # VIP 永不 4296fallback_chain:7 - claude-sonnet-4-58 - claude-3-5-sonnet9 - gpt-4o-mini签发到这个 Group 下的 Key 自动享受高配额 + 永不 429 的兜底体验。
5.5 营销活动 / 限时抢购#
零点开抢 → 流量 100x 平时。Burst Pool 模式:
1group: campaign-double112quota:3 rpm: 1_000 # 日常4burst:5 enabled: true6 multiplier: 50 # 允许 50,000 RPM7 duration: 600 # 持续 10 分钟8 triggers_per_day: 2 # 每天最多触发 2 次9 cooldown: 1800 # 触发后 30 分钟冷却10on_exceed: queue # 突发期内仍超就排队兼顾日常成本控制 + 活动体验。
5.6 月底刹车#
预算只剩 5%、还有 3 天 → 想刹车但不立刻停摆:
1group: prod-api2quota:3 monthly_budget_usd: 50_0004soft_budget_usd: 47_500 # 95% 触发软告警5on_budget_exceeded: queue # 排队不拒绝6on_budget_breach: 7 threshold_pct: 1008 action: reject_writes_only # 只拒绝新签发,已有调用继续放行控制台 Webhook 通知财务,开发同学有缓冲时间,不会突然全员断电。
6. End-User 级限流(最被低估的能力)#
这是做 SaaS 的人最该用、却最少用对的能力。
不论你是面向个人开发者的 PaaS、面向企业客户的 SaaS、还是构建 AI 助手类应用,在 Hydite 上你都可以对自己的"客户的客户"做限流。
只需要业务侧把 end-user-id 透传给 Hydite:
1# OpenAI SDK 标准方式2client.chat.completions.create(3 model="claude-sonnet-4-5",4 messages=[...],5 user="customer_42", # OpenAI 协议的 user 字段6 extra_body={"metadata": {"user_id": "customer_42"}}, # 也支持 metadata7)Hydite 会基于这个 ID 维护一个独立的限流计数器,所有 RPM / TPM / Budget 都可以直接套到 end-user 上。
| 价值 | 收益 |
|---|---|
| 防止单个客户脚本 bug 拖垮整个池子 | 一个失控终端不能 DDoS 你 |
| 实现"按用户计费"的产品 | 每个用户消耗多少美元,控制台直接读 |
| 实现"免费/付费/VIP"分层 | 不同 metadata.tier 走不同 Group |
| 应对监管「按个人数据使用记录留存」 | end-user 维度审计成原生支持 |
强烈建议任何对外提供 LLM 能力的 SaaS / PaaS / Agent 产品都启用 end-user 限流。 它能从架构上避免 90% 的"客户成事故源"。
7. 时间维度限流#
很多业务有明显的潮汐:
1group: prod-api2quota:3 rpm: 10_000 # 默认4schedule:5 - cron: "0 0-7 * * *" # 凌晨 0~7 点6 rpm: 500 # 大幅压低7 - cron: "0 9-18 * * 1-5" # 工作日 9~18 点8 rpm: 30_000 # 高峰期放开9holidays:10 - "2025-01-29 to 2025-02-04" # 春节11 rpm: 200适合:
- 国别 / 时区敏感业务:营销活动只在某个时区放开。
- 成本控制:非高峰期压低,把资源还给批任务。
- 业务保护:法定节假日或特殊事件期间临时收紧。
控制台 → Group → Schedule 的 GUI 编辑器内置常见模板,无需写 cron。
8. 限流响应规范#
被限流时,所有 API 返回标准的 OpenAI 风格错误体 + 一组扩展头:
1HTTP/1.1 429 Too Many Requests2Content-Type: application/json3Retry-After: 124X-RateLimit-Limit-Requests: 10005X-RateLimit-Limit-Tokens: 2000006X-RateLimit-Remaining-Requests: 07X-RateLimit-Remaining-Tokens: 08X-RateLimit-Reset-Requests: 12s9X-RateLimit-Reset-Tokens: 12s10X-Hydite-Limit-Layer: group11X-Hydite-Limit-Group: grp_acme_prod12X-Hydite-Limit-Counter: rpm1{2 "error": {3 "type": "rate_limit_error",4 "code": "rpm_limit",5 "message": "Rate limit exceeded for group grp_acme_prod (1000 RPM). Retry in 12s.",6 "param": null,7 "_extra": {8 "layer": "group",9 "limit": 1000,10 "remaining": 0,11 "reset_seconds": 12,12 "counter": "rpm"13 }14 }15}Hydite 扩展头的作用:
X-Hydite-Limit-Layer告诉你是哪一层限流命中(org/group/team/key/user)。X-Hydite-Limit-Counter告诉你是哪个计量被打满(rpm/tpm/concurrency/budget)。- 三秒定位问题,不需要翻日志。
9. 客户端最佳实践#
不论 SDK 还是裸 HTTP,遵循以下三件事即可:
9.1 看 Retry-After 退避#
不要硬等 60 秒、不要立即重试。Retry-After(秒)是 Hydite 计算出的下一个安全重试时刻:
1import time, openai2def call_with_retry(fn, max_attempts=5):3 for i in range(max_attempts):4 try:5 return fn()6 except openai.RateLimitError as e:7 wait = float(e.response.headers.get("retry-after", 2 ** i))8 time.sleep(wait + random.random()) # 加 0-1s jitter 避免雪崩9 raise RuntimeError("Exhausted retries")9.2 在客户端用 Token Bucket 自我节流#
如果你已经知道自己的限额(如 1000 RPM),客户端先做一遍 Token Bucket,让流量出门时就是平滑的:
- 减少触发限流次数 → 减少 429 → 用户体验更好。
- 减少不必要的网关往返 → 略微降低延迟。
任何成熟 SDK 框架(Resilience4j / aiolimiter / p-throttle)都能 5 行代码搞定。
9.3 流式调用尽早放弃错误请求#
流式调用在中途遇到限流也会立刻断流。SSE 客户端要监听 error 事件并立刻关闭连接,不要傻等:
1const stream = await openai.chat.completions.create({...})2for await (const chunk of stream) {3 if (chunk.choices?.[0]?.finish_reason === "content_filter") break4 // ...5}10. 可观测性#
控制台 Overview → Rate Limits 提供:
- 实时计数器仪表盘:每个 Group / Key 当前的 RPM / TPM / Concurrency / Budget 利用率。
- 触发事件流:最近 24h 所有 429 / Queue / Fallback / Burst 的发生时间、击中层、计量、来源。
- TopN 限流来源:哪些 Key、IP、end-user 是触发限流的"惯犯"。
- 历史趋势:限流率(被限/总调用)、配额利用率、Burst 触发次数。
API:
GET /spend/rate-limits/timeseries?group_id=...— 时间序列GET /spend/rate-limits/events?layer=group&counter=tpm— 事件流GET /spend/rate-limits/topn?n=20&dim=user_id— Top 触发来源
也可推送到 Prometheus / Datadog(详见 Shared Edge · 可观测性)。
11. 档位差异#
| 能力 | 共享 | 订阅 Pro / Team / Business | 企业定制 |
|---|---|---|---|
| RPM / TPM | 平台预设 | 按档位 | 不限 |
| Concurrency 限流 | — | ✅ | ✅ |
| Budget(月度) | ✅ | ✅ | ✅ |
| Soft Budget(告警线) | — | ✅ | ✅ |
| End-user 限流 | — | ✅ | ✅ |
| Queue / Fallback 模式 | Reject | Reject + Queue | 全部模式 |
| Burst Pool | — | Business+ | ✅ |
| 时间窗口 / 节假日 | — | Business+ | ✅ |
| 算法选择 | Sliding Window | 4 种均可 | 4 种均可 |
| Webhook 告警 | 邮件 | 多通道 | 多通道 + SIEM |
详见 Shared Edge Instance 与 Dedicated Instance。
12. 反模式(不要这样配)#
- ❌ 只配 RPM 不配 TPM:一次 200k 上下文调用就能击穿你的 TPM 预算,但你完全没看到。
- ❌ 预算只设硬上限不设软上限:到点直接全员断电,没有预警时间。
- ❌ End-user 限流写在 Key 的 metadata 里而不是请求里:一个 Key 服务 1000 个用户时,Key 级限流毫无意义。
- ❌ 限流触发后给所有 Key 都用 Reject:VIP 用户也 429 是产品事故。
- ❌ 客户端不看
Retry-After死循环重试:把网关打成 DDoS 自残。 - ❌ Org / Group / Key 三层都不分,全都打在 Key 上:升级、复用、转售时全部要重做。
- ❌ 流式调用不监听 error:客户端会卡到超时,体验灾难。
13. 一份能直接复制的起步配置#
1# 一个典型生产 Group 的"黄金配置"2group: prod-api3quota:4 rpm: 60_0005 tpm: 20_000_0006 concurrency: 2007 monthly_budget_usd: 50_0008soft_budget_usd: 47_5009algorithm: sliding_window10on_exceed: reject11on_budget_exceeded: queue12end_user_limit:13 rpm: 10014 tpm: 200_00015schedule:16 - cron: "0 9-18 * * 1-5"17 rpm: 90_00018alerts:19 webhook: https://hooks.acme.com/hydite-alerts20 thresholds:21 budget: 8022 rpm_utilization: 90把它丢进控制台 Group → Edit Policy 就能跑。
下一步
- 多 Key 治理基础 → API Key Groups
- 自定义子域名 → Custom Domains
- 接口与扩展头 → API Reference