图像生成流水线的速率限制与排队
1 分钟阅读作者 genmux API Team
演示和生产级图像流水线的差别,就在于负载 95 分位时会发生什么。本文讲你会遇到的两种限制、能优雅应对它们的客户端架构,以及算清真实吞吐量的容量公式。
两种限制
- 单密钥 RPS(默认每秒 10 次):你可以多快地「跟」API 说话。超出会返回
429 rate_limited,并带Retry-After。 - 单账户最大在途任务数(默认 20):同时处于「排队中或执行中」的任务上限。超出会返回
429 too_many_inflight。GET /v1/account会同时给出inflight和max_inflight,所以你能实时看到余量。
RPS 保护的是前门;在途数保护的是生成队列的公平性。两者都可以调高——当你的稳态确实需要时,从控制台申请即可。
不会熔断的客户端架构
把工作压进你自己的有界队列,而不是把用户请求直接怼到 API 上:
text
用户请求 → 你的队列 → N 个 worker(N ≤ max_inflight)→ 提交 → webhook/轮询 → 交付- N 由限额决定,而不是由期望决定。 在
max_inflight = 20、生成中位数约 8 秒的情况下,你的上限是持续约 2.5 张/秒(20 ÷ 8)。想要 10 张/秒?那是一次「申请提高限额」的对话,不是一个重试循环能解决的。 - 把 429 当作背压,而不是错误。 按
Retry-After睡一会儿,别把它计入用户可见的失败,也绝不要换一个新的 Idempotency-Key 去重试(别处的重复扣费 bug 就是这么来的;在这里它只会白白占掉一个队列名额)。 - 按优先级分流。 面向用户的请求走一个队列,批处理/回填走另一个;只有当
inflight < max_inflight × 0.7时才放批处理的量。
尖峰、失败,以及被你避开的死亡螺旋
经典的失效模式:流量尖峰 → 超时 → 客户端重试 → 重试流量把尖峰又翻了一倍。这里有两个特性可以打断这个螺旋:
- 提交很轻,即使生成队列很深也在毫秒级应答——你的请求不会超时,只会排队。
- 用同一个
Idempotency-Key重试提交是免费的空操作,所以再激进的重试策略也无法把负载放大成双倍工作。
再给传输层错误加上带抖动的指数退避(0.5 秒 → ×1.6 → 上限 5 秒)就够了——API 这条路径不需要熔断器。
值得盯的监控
盯三个数字:你的队列深度、inflight / max_inflight,以及按 error.code 分类的任务失败率。失败尖峰不会让你损失积分(自动退回),但它是提示词有问题或上游出状况的最早信号。其余的一切——余额、单任务费用、流水——服务端都已经对好了(怎么做到的)。