教程
图像生成 API 速率限制详解:预期情况与 HiAPI 如何应对突发流量
图像 API 中“速率限制”的真实含义
当图像生成请求以 HTTP 429 失败,或者你的批量任务每次都在完全相同的并发数上卡住时,你遇到的是速率限制——而不是 bug。所有生产级图像 API 都至少从三个维度之一对流量进行限制,而理解这些区别对调试至关重要:
- RPM(每分钟请求数)——在滚动 60 秒窗口内可以发出的
POST调用次数。对突发流量友好,恢复速度快。 - RPD(每天请求数)——每日上限,通常与你的套餐层级挂钩。在 UTC 午夜(或你账户的计费日)重置。
- 并发数 / 进行中任务数——可以同时运行的图像任务数量。即使 RPM 正常,第 5 个进行中的任务也会被排队或拒绝。
具体到图像生成,瓶颈几乎总是并发数,而非 RPM——单个 1024×1024 任务端到端可能需要 8–30 秒,所以 10 个并行任务 ≠ 10 RPM。把这两者混为一谈是“我的重试让情况更糟”的最常见原因。
常见原因按命中率排序
- 你的并行度超过了并发上限。最可能的原因。你的循环一次性发出 50 个
POST /v1/tasks调用,提供商接受前 N 个,其余返回429。大多数提供商的并发上限不会按密钥单独文档化——而是根据你的层级推断的。 - 瞬时错误后的重试风暴。一个任务返回 5xx 会立即触发重试,所有其他进行中的任务也做同样的事,你的有效并发数在一秒内翻倍。
- 你不知道的按模型 RPM 上限。一个高 tier 的通用密钥可能仍受模型维度的限制,尤其是对新模型或高级模型。用同一个密钥调用
gpt-image-2和flux-1-pro并不意味着它们共享一个配额。 - 每日配额在中午耗尽。不太常见但最令人困惑——你的请求正常工作,然后每天在同一墙钟时间开始失败。始终是 RPD。
- 共享子账户上的噪音邻居。如果你按环境配置密钥但它们共享一个计费账户,预发流量会吃掉生产配额。
修复步骤
按顺序执行以下步骤。每一步隔离不同的维度。
读取错误响应体,而不只是状态码。来自 HiAPI 的真实
429如下所示:{ "error": { "code": "rate_limit_exceeded", "type": "hiapi_error", "request_id": "req_01HXXXXXXXXXXXXXXX" } }记下
request_id。这是让支持团队精确追踪你触发了哪个限制的唯一信息。区分 429 与 401。带有
{"error":{"code":"permission_denied","type":"hiapi_error","request_id":...}}的401不是速率限制——而是认证或权限失败。不要对 401 添加退避;无论等多久它都不会变成 200。先限制客户端并发,再限制重试次数。一个简单的信号量就够了:
import asyncio, httpx sem = asyncio.Semaphore(4) # 将此值匹配提供商的并发上限 async def submit(client, payload): async with sem: return await client.post("https://api.hiapi.ai/v1/tasks", json=payload)从 4 开始。只有在整批任务运行且没有一次 429 后,才调高。
仅在 429 时使用带完全抖动的指数退避。
import asyncio, random async def backoff(attempt): # 1s, 2s, 4s, 8s,上限 30s,随机化以避免惊群效应 delay = min(30, 2 ** attempt) * random.random() await asyncio.sleep(delay)重试次数上限设为 5。之后暴露失败——不要无限重试。
存在
Retry-After时遵从它。如果响应带有Retry-After头,那是提供商在明确告诉你窗口何时重置。那一次重试应使用它,而不是你计算的退避值。按环境分离密钥。如果预发和生产共享一个密钥,你的并发上限也是共享的。每个环境一个密钥 + 每个高流量工作池一个密钥,是解决“限制感觉比文档说的更低”的最便宜方法。
HiAPI 如何处理突发流量
HiAPI 前置了一个 POST /v1/tasks 端点,它接受你的任务后立即返回任务 id,然后你轮询完成状态。这种拆分对速率限制的计算很重要:创建调用开销低且耗时短,所以 RPM 限制宽松;重负载工作由模型侧的并发控制,这才是它该在的地方。当下游提供商拥塞时,创建调用仍然成功——你的任务只是在队列中等待,GET /v1/tasks/{id} 在槽位打开前返回 status: "queued"。你永远不会因下游的瞬时压力看到 429;只有当你超出自己密钥的配额时才会看到。
这就是当团队的图像工作负载超出单个账户承载能力时,从直接集成提供商迁移到 HiAPI 的实际原因:一个 Bearer 密钥、一个可推理的速率限制预算,突发流量由队列吸收,而不是由你的重试循环吸收。
最小验证示例
用它确认你的密钥正常且并发设置合理。它向 gpt-image-2 提交一个图像任务并打印任务 id:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": "a single red apple on a wooden table, soft daylight",
"aspect_ratio": "1:1",
"resolution": "1K"
}
}'
预期响应:
200附带{"id":"task_...","status":"queued"}→ 密钥正常,配额没问题。429附带{"error":{"code":"rate_limit_exceeded",...}}→ 你超过了 RPM、RPD 或并发限制。按上述修复步骤减速。401附带{"error":{"code":"permission_denied",...}}→ 认证失败,不是速率限制。检查你的密钥。
用快速的 seq 1 10 | xargs -n1 -P10 curl ... 循环重复此调用,以找到你的并发上限——第一个返回 429 的标记了你的有效上限。
相关阅读
- HiAPI 任务挂起与超时诊断——当任务在
queued或processing状态停留超过预期时。 - 为什么你的 HiAPI 任务回调没有触发——
/v1/tasks流程的异步回调排查。 - 解决
model_not_available错误——相邻的错误类别,常被误读为速率限制。 - 模型目录——按模型定价和端点类型。
- 定价——逐 tier 明细。
常见问题
HiAPI 上 gpt-image-2 有公开的 RPM 数值吗?
限制基于 tier,且可能随提供商调整各自上限而变化。请查看你的仪表盘获取当前有效限制,而不是硬编码博客文章里的数字。
为什么重试有时会让 429 更糟?
在 N 个并行 worker 上朴素地使用 sleep(1) 重试,会把一个 429 变成 N 个同步重试,全部再次命中。使用完全抖动(sleep * random.random()),而不是固定延迟。
HiAPI 对 429 响应收费吗? 不收费。失败的任务创建(429、401、一般 4xx)不计费。你只为成功产生输出的任务付费。
客户端提高并发能提升我的上限吗? 不能。并发上限是服务端按密钥设定的。客户端并行度只决定你是保持在上限之下还是触发它。
RPM 和 TPM 有什么区别?
图像 API 按请求(RPM)限制,而不是 token(TPM)——图像任务没有有意义的“token”单位。如果你在仪表盘中看到 TPM 限制,它适用于文本/聊天端点,而不是 /v1/tasks 图像任务。
我应该使用一个高并发密钥还是多个低并发密钥? 对于图像工作负载,每个逻辑工作池一个密钥是最简单的心智模型。一个计费账户下的多个密钥实际上不会倍增你的配额——它们共享配额。
我可以申请更高的并发上限吗?
可以——一旦你在当前 tier 展示了持续使用量。向支持团队提供代表性 429 的 request_id,他们可以追踪你命中的是哪个维度。
为什么我没有看到 Retry-After 头?
并非所有提供商都会发送。缺失时,回退到从 1s 开始的带抖动指数退避。存在时,那一次重试应信任它。