VanaAPI

← 文章

并发请求遇到 429 时的一页处理记录

接口格式ZH2026-10-30

批量任务运行正常,直到几个请求同时收到 429。此时最容易写下的处理逻辑是“失败就再发一次”,但这可能让短暂拥堵变成持续拥堵。更稳妥的办法,是把等待、并发和失败边界一起设计。下面将两种处理方式并排记录:一种追求立刻恢复,另一种让恢复过程保持可控。

§ 读到响应:直接重发,还是先判断限制

直接重发:只检查状态码,把所有 429 都当成瞬时拥堵。这样实现简单,却无法区分请求频率过高、令牌吞吐受限,以及需要人工处理的额度问题。

先判断限制:同时读取错误正文和实际返回的响应头。如果有 Retry-After,按其秒数或日期计算等待时间;如果没有,再使用本地退避策略。不要假定每个接口都有相同的限流响应头,也不要仅凭 429 推断限制来自哪一层。

§ 安排等待:固定间隔,还是带抖动的退避

固定间隔:所有工作进程每隔一秒重试,看起来公平,却容易让它们在下一秒再次同时撞上限制。任务越集中,这种同步重试越明显。

带抖动的退避:没有服务端等待指引时,逐次扩大等待窗口,并在窗口内随机取值。例如将窗口从一秒扩大到两秒、四秒,再设一个上限。这些数值只是应用配置示例,不是 Vana API 的限额。若收到有效的 Retry-After,不应为了随机化而提前重试;等待过长、超出任务期限时,应结束本次尝试。

§ 控制流量:只重试失败项,还是约束整体入口

只重试失败项:旧请求进入重试队列,新请求继续无限进入。即使退避正确,总负载仍可能超过可用容量。

约束整体入口:为新请求和重试请求共用一个并发预算,使用有界队列吸收短时波动,并在持续出现 429 时降低发送速率。多个实例处理同一类任务时,还要协调总流量,避免每个实例都认为自己“只发了一点”。令牌消耗差异明显的请求,也不宜只按请求数量估算负载。

§ 设置边界:一直等成功,还是明确停止条件

一直等成功:重试次数没有上限,用户关闭页面后后台仍在等待。系统可能最终完成任务,却已经超过业务允许的时间。

明确停止条件:同时设置最大尝试次数、总耗时预算和取消信号。每次等待前检查剩余时间,不够就停止。使用 OpenAI SDK 连接 Vana API 时,还应检查当前 SDK 版本的自动重试设置,避免外层任务队列与内层客户端叠加重试。

§ 恢复输出:整段重跑,还是保留执行边界

整段重跑:无论有没有收到内容,都重新发送同一请求。这可能让用户看到重复文本;若应用已经执行工具调用,还可能重复发送消息或修改数据。

保留执行边界:将明确收到的 429 与流中断、超时分别处理。流式响应已经开始后,不要把部分输出和新结果直接拼接。记录已展示内容和工具执行状态,为外部副作用单独设计去重机制。不能默认兼容某种协议,就意味着所有请求都支持幂等键,或能够从断点继续。

§ 验证策略:看单次成功,还是看恢复代价

看单次成功:测试只确认“重试后有结果”,却忽略等待时间、队列增长和重复工作。

看恢复代价:记录初始请求量、429 比例、重试次数、累计等待和最终失败率;响应里若提供请求标识,也一并保存。Vana API 的统一入口支持 OpenAI 兼容接口、Anthropic Messages 和 Gemini 原生协议,但应用仍应按实际协议和客户端验证错误处理,而不是假定行为完全一致。

可以创建一个 Vana API 账户,先用小规模任务验证这套策略。测试目标不是让每个请求无限接近成功,而是在限制出现时,系统能够减速、停止,并清楚说明发生了什么。