重试不是多跑一次:给 HTTP 客户端补上幂等边界
很多客户端在遇到超时后会立刻再请求一次,看起来只是“多跑一次”,实际却可能创建两条订单、发送两封邮件,或者在任务系统里留下两个执行实例。超时只说明客户端没有及时拿到结果,并不代表服务端没有处理请求。真正可靠的自动重试,必须同时回答三个问题:这次请求能不能重试、重试后如何识别同一次业务操作、什么时候应该停止。
第一步是按语义给请求分类。查询类请求通常可以安全重试,创建和修改类请求则需要额外条件。网络断开、连接超时和部分 5xx 可以进入重试队列;参数错误、认证失败等 4xx 不应该盲目重试;429 虽然可以重试,但应优先遵守服务端返回的 Retry-After。不要把所有异常统一包成一个 retry(),否则很容易把不可重试的业务错误变成重复提交。
第二步是引入业务幂等键。客户端在第一次发送前生成稳定的请求标识,并在所有重试中复用,例如:
const request = {
method: "POST",
headers: {
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
};
幂等键不能每次重试都重新生成,否则服务端只会把它看成多次不同的创建请求。服务端需要保存键与处理结果之间的映射,并在重复请求到来时返回第一次的结果,而不是再次执行业务逻辑。这里还要明确有效期和并发语义:两个使用相同键的请求同时到达时,后到的请求应等待第一个完成,或者返回明确的处理中状态。
第三步是给重试设置预算,而不是无限循环。一个常见组合是有限次数、指数退避和随机抖动。抖动可以避免大量客户端在同一时刻再次冲击服务。日志中应记录尝试次数、错误类别、请求标识和最终结果,但不要记录完整正文、令牌或用户敏感信息。这样出现问题时,能够判断是网络抖动、服务端过载,还是客户端错误地重试了不可重试的操作。
最后还要承认边界:幂等键只能保护已经正确实现的服务端;流式接口、长任务和人工审批不能简单套用同一策略。对本地 AI 客户端而言,一套可交付的重试机制至少应做到:请求语义清楚、标识在重试间稳定、退避有上限、失败可解释、日志不泄密。把这些边界写进代码和测试,自动重试才是可靠性能力,而不是重复执行的放大器。
- 点赞
- 收藏
- 关注作者
评论(0)