跳转到内容

重试、超时与幂等

OpenAI 与 Anthropic 的官方 SDK 默认会自动重试(通常 2 次)。在直连模型服务时这没什么,在网关后面则不然:

Halro 在把请求发往上游之前就把预算预留写入账本,并且这个预留是持久的。客户端的一次静默重试 = 一次全新的、独立的预留与结算。SDK 帮你「悄悄重试两次」的结果,是账上出现三笔而不是一笔。

client = OpenAI(base_url="...", api_key=..., timeout=60.0, max_retries=0)
const client = new OpenAI({ baseURL: "...", apiKey: ..., timeout: 60_000, maxRetries: 0 });

关掉之后,重试策略由你自己写 —— 下面是判断依据。

情况能否重试说明
429 每源限流 / Project 限流可以Retry-After(可能不存在,见下),退避后重试
429 并发上限可以同上
503 provider_unavailable可以当前没有健康的 Deployment
上游 5xx网关已替你试过Halro 内部的回退是有界的;返回给你时说明它已经放弃
403 token_guard_blocked不要价格超出策略上限,重试多少次都是同一个结果
403 model_not_allowed / 404 model_not_found不要配置问题,找管理员
400 字段被拒不要请求本身不合法,改请求
结果不明确的失败谨慎见下一节

结果不明确的失败,网关不会替你重试

Section titled “结果不明确的失败,网关不会替你重试”

如果一次上游调用的结果是歧义的 —— 例如连接在请求已发出但响应未回来时断开 —— Halro 不会重试它,也不会把费用退掉。这是有意的:无法确定上游是否已经产生了计费事件时,账目按发生过保守处理,而不是乐观地假设它没发生。

所以这类失败给你的是一个错误,而账上可能已经有一笔。你自己重发是允许的,但要清楚那会是第二笔独立的费用。

创建型的资源端点接受 Idempotency-Key 请求头 —— 异步调用(POST /v1/async/invocations)、文件创建(POST /v1/files)、批处理创建(POST /v1/batches)。带上它,重复提交同一个键不会创建第二个资源。

Terminal window
curl https://halro.example.com/v1/files \
-H "Authorization: Bearer $HALRO_GATEWAY_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-F purpose=batch -F file=@input.jsonl

推理端点(chat / responses / messages)不走这套。 那里没有幂等键可用,所以上一节那条规则更重要:结果不明确时,重发就是一笔新的费用。

只在能算出一个正数等待时长时才写入。每源限流与 Project 限流会带;Deployment 并发那条不设置;上游透传的 429 只在上游自己带了可解析的头时才有。读不到就用你自己的退避策略,不要假设它一定存在。

没有放之四海的建议值 —— 它取决于你的模型和 max_tokens。两个原则:

  • 超时要长于你允许的最长生成时间,否则你会在上游正常工作时把连接掐掉,而那正好落进上一节说的「结果不明确」。
  • 流式请求的超时应当针对单个事件间隔,而不是整个响应,否则长回答必然超时。