HiAPI
博客

教程

图像生成 API 速率限制详解:预期情况与 HiAPI 如何应对突发流量

2026年11月3日
图像生成 API 速率限制详解:预期情况与 HiAPI 如何应对突发流量

图像 API 中“速率限制”的真实含义

当图像生成请求以 HTTP 429 失败,或者你的批量任务每次都在完全相同的并发数上卡住时,你遇到的是速率限制——而不是 bug。所有生产级图像 API 都至少从三个维度之一对流量进行限制,而理解这些区别对调试至关重要:

  • RPM(每分钟请求数)——在滚动 60 秒窗口内可以发出的 POST 调用次数。对突发流量友好,恢复速度快。
  • RPD(每天请求数)——每日上限,通常与你的套餐层级挂钩。在 UTC 午夜(或你账户的计费日)重置。
  • 并发数 / 进行中任务数——可以同时运行的图像任务数量。即使 RPM 正常,第 5 个进行中的任务也会被排队或拒绝。

具体到图像生成,瓶颈几乎总是并发数,而非 RPM——单个 1024×1024 任务端到端可能需要 8–30 秒,所以 10 个并行任务 ≠ 10 RPM。把这两者混为一谈是“我的重试让情况更糟”的最常见原因。

常见原因按命中率排序

  1. 你的并行度超过了并发上限。最可能的原因。你的循环一次性发出 50 个 POST /v1/tasks 调用,提供商接受前 N 个,其余返回 429。大多数提供商的并发上限不会按密钥单独文档化——而是根据你的层级推断的。
  2. 瞬时错误后的重试风暴。一个任务返回 5xx 会立即触发重试,所有其他进行中的任务也做同样的事,你的有效并发数在一秒内翻倍。
  3. 你不知道的按模型 RPM 上限。一个高 tier 的通用密钥可能仍受模型维度的限制,尤其是对新模型或高级模型。用同一个密钥调用 gpt-image-2 和 flux-1-pro 并不意味着它们共享一个配额。
  4. 每日配额在中午耗尽。不太常见但最令人困惑——你的请求正常工作,然后每天在同一墙钟时间开始失败。始终是 RPD。
  5. 共享子账户上的噪音邻居。如果你按环境配置密钥但它们共享一个计费账户,预发流量会吃掉生产配额。

修复步骤

按顺序执行以下步骤。每一步隔离不同的维度。

  1. 读取错误响应体,而不只是状态码。来自 HiAPI 的真实 429 如下所示:

    {
      "error": {
        "code": "rate_limit_exceeded",
        "type": "hiapi_error",
        "request_id": "req_01HXXXXXXXXXXXXXXX"
      }
    }
    

    记下 request_id。这是让支持团队精确追踪你触发了哪个限制的唯一信息。

  2. 区分 429 与 401。带有 {"error":{"code":"permission_denied","type":"hiapi_error","request_id":...}} 的 401 不是速率限制——而是认证或权限失败。不要对 401 添加退避;无论等多久它都不会变成 200。

  3. 先限制客户端并发,再限制重试次数。一个简单的信号量就够了:

    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 后,才调高。

  4. 仅在 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。之后暴露失败——不要无限重试。

  5. 存在 Retry-After 时遵从它。如果响应带有 Retry-After 头,那是提供商在明确告诉你窗口何时重置。那一次重试应使用它,而不是你计算的退避值。

  6. 按环境分离密钥。如果预发和生产共享一个密钥,你的并发上限也是共享的。每个环境一个密钥 + 每个高流量工作池一个密钥,是解决“限制感觉比文档说的更低”的最便宜方法。

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 上 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 开始的带抖动指数退避。存在时,那一次重试应信任它。

立即开始构建持久 AI 产物

获取 API 密钥,通过一个基于任务(task)的 API 调用图像、视频和音频模型。

阅读 API 文档