限流与配额

API 限流方式速览

三种常见限流维度

维度全称含义类比
RPMRequests Per Minute每分钟可发起的请求次数收银台「每分钟接待多少人」
TPMTokens Per Minute每分钟可处理的 token 总量厨房「每分钟能出多少菜量」
Concurrency并行任务数同一时刻正在执行中的任务数量上限餐厅「同时在做的菜不超过 N 份」

简单记忆:RPM 关心「叫了几次」,TPM 关心「工作量多大」,Concurrency 关心「同时有几个在跑」。

核心区别

RPM / TPM 是速率类限流:关注一段时间内累计的请求次数或数据量,请求发完就释放,时间窗口一过就重置。

Concurrency 是存量类限流:关注「同一瞬间有多少任务正在占用资源」,只要任务还没结束,就会持续占用名额。

举例(假设配额 Concurrency = 2):

  • 10:00:00 提交任务 A(预计耗时 5 分钟)
  • 10:00:01 提交任务 B(预计耗时 5 分钟)
  • 10:00:02 提交任务 C → 被拒绝或排队,因为 A、B 仍在跑
  • 10:05:00 任务 A 完成,名额释放,C 才能开始

为什么生图 / 生视频等异步任务用 Concurrency 限流

文本对话类接口通常秒级返回,一次请求占用算力的时间很短,用 RPM / TPM 足以反映真实负载。但生图、生视频等任务不同:

  1. 单任务耗时长:一张图几秒到几十秒,一段视频可能几分钟,「每分钟几次」无法反映 GPU 的实际占用时间。
  2. 资源是 GPU 显存而非 token 带宽:任务一旦开始就独占一块 GPU 资源直到结束——算力是「被占住的」,不是「流过的」。
  3. RPM 会严重失真:若只限 RPM=60,一分钟内提交 60 个各跑 3 分钟的视频任务,瞬间就有 60 个任务堆在 GPU 上争抢,导致服务过载。
  4. 异步任务天然适配并发模型:接口提交后立即返回任务 ID,真实执行在后台排队,Concurrency 正好描述「后台 worker 池的容量」。

一句话总结:Chat 类是「流量型」负载,按速率限流合理;生图 / 生视频类是「占用型」负载,按并发限流才合理。

如何在客户端控制 Concurrency

  1. 维护一个「在途任务计数器」:每次提交 +1,收到最终状态(成功/失败/超时)-1。
  2. 用信号量或任务队列:例如 Python 的 asyncio.Semaphore(N)、Go 的带缓冲 channel,或 Redis / RabbitMQ 做削峰。
  3. 收到 429 / 并发超限错误时指数退避:不要硬重试,否则会把后端越压越死。
  4. 轮询任务状态要有节制:查询本身也算请求,建议间隔 ≥ 3–5 秒,能用 Webhook 回调就不要轮询。
  5. 提前规划配额:按业务峰值 QPS × 平均任务耗时估算所需并发数。例如高峰每秒 2 个任务、每个平均 30 秒,则至少需要 Concurrency = 60。

常见误区:

  • ❌ 「RPM 够大就不会被限」:长耗时任务会先撞到 Concurrency 上限。
  • ❌ 「任务提交成功就等于立刻执行」:异步接口的 202 只代表「已接收」,实际开始时间取决于队列和可用名额。
  • ❌ 「把客户端改成多线程就能提速」:如果服务端 Concurrency 是 5,开 50 个线程也只有 5 个在跑,其余全在排队。

各字段的实际生效范围

同一用户的限流配额按以下顺序匹配,命中即停止下探:用户专属配置(按模型)→ 用户默认配置 → 系统兜底配置 + 充值档位

RPM(每分钟请求数)

适用于以下三类接口:

  • 对话类(同时受 RPM + TPM 控制):/v1/chat/completions/bypass/openai/v1/chat/completions/bypass/openai/v1/responses/bypass/anthropic/v1/messages/bypass/vertex/v1/*/bypass/vertex/v1beta/*
  • 图片 / 搜索类(同时受 RPM + TPM 控制):/v1/images/generations/v1/images/edits/v1/search/web
  • 视频生成类(仅按「每次提交计 1 次请求」参与 RPM):/v1/videos/v1/videos/{id}/remix/v3/contents/generations/tasks,以及 /queue/** 下所有异步视频提交类接口(含 Seedance、Vidu、Kling、Veo、Dreamina 等 Fal / 火山格式队列;不含 .../requests/{id} 状态/结果查询)。

TPM(每分钟 Token 数)

只在真正会预估 Token 消耗的接口上有约束意义:

  • 全部对话类接口:消耗估算 ≈ 输入字符数 / 3 + max_tokens(未传时默认按 4096 预留)。
  • 图片生成与编辑接口:消耗估算 ≈ prompt 字符数 / 3 + 张数 × 1000。

预估公式、与 usage.total_tokens 的差异及优化建议详见 TPM 是如何计算的

⚠️ 视频生成接口和搜索接口虽然也走该限流通道,但每次只计 1 个 Token,对 TPM 没有实际限制效果,请不要把 TPM 当作视频/搜索接口的额度控制手段。

Concurrency(异步任务并发数)

仅对异步视频生成类接口生效,按 (用户, 模型) 维度独立计数:/v1/videos/v1/videos/{id}/remix/v3/contents/generations/tasks,以及 /queue/** 下所有异步视频提交类接口(规则同 RPM 段落;不含任务状态/结果查询)。槽位会在任务终态(成功 / 失败 / 取消)时自动释放,并配有兜底超时回收。

不受这三个字段约束的接口

以下接口不会消耗 RPM / TPM / Concurrency 中的任意一项(可能仍受 RPS、API Key 额度、订阅套餐等其它机制约束):文本补全 /v1/completions、MCP / Agent 系列 /v1/mcp/.../v1/agent/...、批量推理 /v1/batchjob/.../v2/batchjob/...

速查表

接口分类RPMTPMConcurrency
对话(chat / bypass / anthropic-bypass / responses / vertex-bypass)
图片生成 / 编辑
联网搜索⚠️ 名义生效
视频生成(含 Seedance / Veo / 标准 videos)⚠️ 名义生效
独立 Anthropic / FIM 补全 / 语音 / OCR / MCP / 批量推理 / 部分队列任务

✅ = 真实生效;⚠️ = 接口走了限流通道但增量为 1,对该字段实际无约束效果;— = 不受该字段约束。

Gemini 限流

Vertex AI 上的 Gemini 模型资源是全球共享的,并没有披露明确的每分钟请求数上限(RPM,与并发数 Concurrency 是不同概念)。当模型被大量请求、系统资源不足时,会返回 429 错误(Resource exhausted / Model resources busy)。建议在业务侧实现请求重试机制。