AI 接口 504 后先查什么:X-Client-Request-Id、退避上限与幂等键
线上 AI 功能最容易出事故的时刻,往往不是模型返回 400,而是客户端等了 30 秒后只收到一个超时。此时服务器可能还在生成,业务却不知道这次请求到底有没有落地。安全做法不是立刻再发一遍,而是给每次业务操作固定请求标识,区分“可以重试”和“必须人工确认”,再用结果键把重复响应收敛掉。
- OpenAI 可用
X-Client-Request-Id记录客户端请求标识,服务端响应还应保存x-request-id便于排查。 - Gemini 官方建议只对超时、网络异常、408、429 和 5xx 等瞬态问题做有限次数的指数退避,并加入抖动。
- 重试前先查本地任务表;没有确定结果时用业务幂等键去重,不能把“重复提交”当成成功。
超时不是失败:先把一次调用拆成三种结果
我在一个“根据用户上传内容生成摘要”的接口上遇到过这个问题:网关 30 秒断开连接,后台日志却显示模型调用在第 34 秒返回成功。前端如果把超时直接当失败,再次点击就会产生两份摘要,甚至重复扣费。
因此,调用记录至少要有 accepted、succeeded、failed 三类最终状态;客户端超时只能写成 unknown。unknown 的意思是“结果尚未确认”,不是“可以马上重做”。
触发器、权限和请求标识要在入口固定
把重试逻辑散落在控制器、队列消费者和 SDK 里,最后很难知道到底重发了几次。更稳的入口是先创建一条业务任务,再让所有下游调用继承同一个 job_id。
job_id = "summary_20260824_01HZX..."
client_request_id = "job_id/attempt-1"
headers = {
"X-Client-Request-Id": client_request_id,
"Idempotency-Key": job_id,
}
X-Client-Request-Id 用来关联一次网络请求,Idempotency-Key 则是应用自己的业务去重键。两者不要混成一个字段:一次任务可能有多次 attempt,但同一个 job_id 仍然只能产生一个业务结果。
流水线按“记录—调用—核对—重试”推进
每个阶段都要有可观察的产物,否则失败后只能凭猜测补请求。
| 阶段 | 必须记录 | 下一步 |
|---|---|---|
| 创建任务 | job_id、输入摘要、业务状态 | 进入 queued |
| 发起调用 | attempt、client_request_id、开始时间 | 等待响应 |
| 收到响应 | HTTP 状态、x-request-id、模型结果 | 写入 succeeded 或 failed |
| 客户端超时 | 超时原因、attempt、最后已知状态 | 先查任务,再决定重试 |
OpenAI 的响应头包含服务端生成的 x-request-id,排查时要和自己的客户端标识一起保存。Gemini 的官方排障建议则明确把指数退避、随机抖动和最大重试次数放在调用方控制之下。
只对瞬态错误重试,退避时间不要写死
一个够用的策略是:第 1 次等待 1 秒,第 2 次等待 2 秒,第 3 次等待 4 秒,每次加一个 0 到 300 毫秒的随机抖动,并把总等待预算封顶。这样不会让一批同时超时的请求在同一秒再次撞向接口。
retryable = status in {408, 429, 500, 502, 503, 504} or network_timeout
delay = min(30, 2 ** attempt) + random.uniform(0, 0.3)
400 参数错误、401/403 鉴权问题、内容被拒绝以及明确的配额耗尽,不属于“多等一会儿就会好”的瞬态故障。对这些错误重试只会放大日志和成本。对于 504 这类没有响应体的情况,也不要假设服务端没有收到请求,应该先查 job_id 和请求标识。
门禁规则:重试前先查结果,成功后拒绝第二份
重试消费者取到 unknown 任务时,先按 job_id 查结果表,再按请求标识查调用日志。若上游已经成功,就把本地任务补成 succeeded;只有确认没有结果,且错误属于可重试集合,才允许发起下一次 attempt。
if task.result_exists:
return task.result
if task.attempts >= 3 or task.total_wait_ms >= 30000:
return mark_manual_review(task)
if task.last_error in RETRYABLE:
return enqueue_retry(task, next_attempt=task.attempts + 1)
return mark_failed(task)
写结果时再加一道数据库唯一约束,例如 UNIQUE(job_id)。应用层判断能减少重复工作,唯一约束负责挡住并发竞态;两道门都需要,不能只依赖其中一层。
失败处理要能回放,也要能停止
给每个任务保留输入摘要、模型名、attempt 列表和最后一次错误,运维才能回答“这次是否真正发到上游”。当同一任务连续三次超时,或者总等待超过 30 秒,进入 manual_review 比无限重试更安全。人工复核可以重新放行,但要沿用原来的 job_id,并生成新的 attempt 记录。
通知内容也别只写“AI 调用失败”。至少带上 job_id、最后的 HTTP 状态、重试次数、x-request-id(如果有)和用户是否已经看到结果。这样值班同学可以从一条通知跳到完整调用链。
相关问题
超时后立刻重试会不会丢结果?
不会因为“等待”本身丢结果,但可能制造重复任务。先把原任务标成 unknown,查询结果或日志,再决定是否重试。
客户端请求标识能代替幂等键吗?
不能完全代替。请求标识适合排查一次 HTTP 调用,幂等键要绑定业务动作,并由自己的任务表和唯一约束保证结果只落一次。
429 和 500 都应该无限重试吗?
都不应该。根据 Retry-After、指数退避和总预算有限重试;超过预算就停止并告警。
把一次重试变成可核对的结果
可靠的 AI 调用流程不是“失败就再试一次”,而是让每一步都能被还原:谁创建了任务、发了第几次请求、上游给了什么请求标识、结果是否已经落库、为什么停止。把这些证据写进任务表和日志后,超时只是一个待核对状态,重试才会成为可控的业务动作。


AI 接口 504 后要不要重发:请求标识、退避与幂等核对
- 上一篇
- AI 接口 504 后要不要重发:请求标识、退避与幂等核对
- 下一篇
- Cloudflare Gateway 怎么识别 MCP 流量:is_mcp 策略与 AI Security 报表实测
-
- 科技周边 · 人工智能 | 5小时前 | API · 异步任务 · ai · 人工智能 OpenAI background Responses API
- AI 推理过程怎么给用户看摘要:Responses API reasoning summary 与隐私边界
- 195浏览 收藏
-
- 科技周边 · 人工智能 | 5小时前 | gemini · AI工程 · 事实核验 · 引用 Gemini API Google Search Grounding AI工程
- Gemini API Google Search Grounding 怎么验收:查询链、引用标注与失败边界
- 191浏览 收藏
-
- 科技周边 · 人工智能 | 14小时前 | 异步任务 · openai · AI API · 接口状态 · 轮询 background OpenAI Responses API queued completed
- OpenAI Responses API background 模式怎么轮询:queued、completed 与超时回收
- 188浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 | API · gemini · AI工程 · 生成式AI Gemini API Context Caching cachedContents
- Gemini API 显式 Context Caching 怎么验收:cachedContents、TTL 与命中统计
- 209浏览 收藏
-
- 科技周边 · 人工智能 | 2天前 | ai · claude · Anthropic API · 文档问答 · 可追溯回答 · Claude 引用 Anthropic Messages API citations document block
- Claude Messages API citations 怎么核对:document blocks、source 与引用位置
- 295浏览 收藏
-
- 科技周边 · 人工智能 | 2天前 |
- Gemini Developer API 怎么做零数据留存:Interactions、File API 与缓存边界核对
- 374浏览 收藏
-
- 科技周边 · 人工智能 | 2天前 |
- Hugging Face Inference Providers 怎么固定 provider:自动路由、fallback 与响应核对
- 309浏览 收藏
-
- 科技周边 · 人工智能 | 2天前 |
- Gemini API thought_signature 怎么处理:手动拼接 function calling 历史避免 400
- 238浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ljg-skills
- ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
- 5167次使用
-
- MELO音乐
- MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
- 4683次使用
-
- UniScribe
- UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
- 4637次使用
-
- 剧云
- 剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
- 4899次使用
-
- 万象有声
- 万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
- 4851次使用
-
- Go 批量 CSV 导入怎么控内存:流式读取、资源预算和失败行回传实战
- 2026-07-20 407浏览
-
- Go JSON 严格解码上线后请求变 400:DisallowUnknownFields 的兼容性故障复盘
- 2026-07-26 174浏览
-
- Go 流式响应怎么做:ResponseController.Flush、SSE 与断开回收的取舍
- 2026-07-26 463浏览
-
- Go 分页接口怎么设计:游标参数、错误码与兼容返回
- 2026-07-26 427浏览
-
- Go nil slice 为什么 JSON 是 null:接口数组字段统一成 [] 的迁移清单
- 2026-06-28 305浏览
