周五上线前:给批量摘要任务加上429指数退避
批量摘要遇到429,先看服务端说了什么
设想一个周五上线前的场景:团队准备给两百篇文章生成摘要。单篇测试正常,批量运行却开始返回429。第一反应可能是立即重发,但此时更该做的是暂停,读清错误信息。
HTTP 429表示一定时间内请求过多,也就是触发了限流。可以把接口想成只有几个窗口的取餐柜台:订单集中涌入,窗口就会请后面的顾客稍等。它不是让你把同一张订单反复塞进去。([datatracker.ietf.org](https://datatracker.ietf.org/doc/rfc6585/))
不过,别只看状态码。有些AI接口也用429表示额度不足。先检查响应中的错误类型和说明:临时限流可以等待;额度耗尽则需要处理额度问题,单纯重试没有用。([developers.openai.com](https://developers.openai.com/api/docs/guides/error-codes?utm_source=openai))
指数退避,就是失败后逐渐多等一会儿
“退避”指暂时让出请求机会;“指数”指等待时间按倍数增长。例如,第一次失败后等1秒,再失败就等2秒,然后是4秒、8秒。不是每次多等1秒,而是每次把等待时间翻倍。AWS的可靠性实践采用这种思路,避免重试继续压迫已经吃紧的服务。([aws.amazon.com](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/))
给摘要任务设计一个起步方案,可以设定:首次正常请求之外,最多额外重试4次,等待时间依次以1、2、4、8秒为基础。这只是便于理解和测试的示例参数,不是任何平台承诺的恢复时间。
还要明确“重试次数”的含义:额外重试4次,意味着最多发出5次请求。把这个定义写进配置说明,避免不同开发者理解不同。
随机抖动,让失败的任务错开重试
如果几十个任务同时失败,又都严格等待1秒,它们可能再次同时撞上接口。随机抖动就是给等待时间加入随机变化,把整齐的一波请求打散。([aws.amazon.com](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/))
本例可以采用一个直观规则:先计算本轮基础等待时间,再额外增加0到1秒的随机延迟。于是第二轮不一定都等2秒,有的等2.2秒,有的等2.8秒。具体范围可以调整,关键是不要让所有任务踩着同一个节拍回来。
Retry-After比本地猜测更值得先看
429响应可能带有Retry-After响应头,告诉客户端何时再试。它可以表示等待多少秒,也可以是一个HTTP日期;这个响应头不是每次都会出现。([datatracker.ietf.org](https://datatracker.ietf.org/doc/rfc6585/))
建议把有效的Retry-After作为最低等待时间,再与本地退避时间比较,取较长者。例如,本地算出2秒,服务端要求10秒,就至少等10秒;不要用自己的短延迟覆盖服务端提示。
如果服务端要求等待的时间已经超过任务剩余期限,就停止当前尝试,把任务留待稍后处理,而不是为了满足本地上限提前重发。
重试预算,需要同时限制次数和总耗时
指数退避不是无限等待的理由。重试本身会增加下游负担,多层系统分别重试还可能放大请求数量,因此需要限制重试,并明确由哪一层负责。([aws.amazon.com](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/))
- 设置最大重试次数,耗尽后返回明确失败状态。
- 设置整个任务的总期限,把等待和请求耗时一起计算。
- 检查所用SDK是否已经自动重试,避免外层再次套用完整重试流程。
- 记录任务编号、错误类型、尝试次数和等待时间,方便排查,不把密钥写入日志。
对于这次批量摘要,我会建议把未完成文章保留在待处理队列中,而不是重跑全部两百篇。已经成功的结果也应保存下来,避免因为少量失败重复执行整批任务。
并发控制负责预防,退避负责恢复
退避处理的是已经发生的失败;并发控制则限制同时在途的请求数量。只调重试参数,未必能解决持续过载,AWS的实践也强调了限制并发的重要性。([builder.aws.com](https://builder.aws.com/content/3EuxuD6bWtQ6gEp9FaKQfd3Z2AM/using-dependency-isolation-to-contain-concurrency-overload?utm_source=openai))
给这个摘要队列做实验时,可以先只允许少量任务同时执行,观察429数量和完成速度,再逐步调整。不要把“并发数”误当成“每分钟请求数”:前者控制同时处理多少任务,后者控制一段时间内发送多少请求。
把同一套重试规则带进模型调用层
如果团队希望通过统一入口接入模型,可以考虑按量付费的RelayVano,并注册账户,用一个小批量摘要任务验证调用流程。它支持OpenAI兼容SDK,便于在应用侧集中管理重试策略;统一入口并不意味着可以忽略限流。
上线前,建议模拟连续返回429、随后成功的情况,再测试始终失败和要求长时间等待的情况。验收目标不是“永远重试到成功”,而是:能恢复时有序恢复,不能恢复时及时停止,而且每篇文章的处理状态都有据可查。