TATECHATLAS
◎ 简体中文
Web 与 API

用截止时间限制 HTTP 重试并处理未知结果

将请求超时与总重试预算分开,解释 Retry-After,并在服务器结果未知时避免重复写入。

本文内容

为整个操作设定一个预算,并在每次尝试和等待前检查剩余时间。仅重试 API 契约允许的方法、错误和响应状态。尊重有效的 Retry-After 值,不要延长截止时间。超时并不能证明写入失败:需要协调未知的 POST 结果,或使用服务器文档中规定的重复数据删除机制。

为整个操作设定预算

每个尝试的超时限制单个请求。总截止时间限制跨尝试和等待期的操作。为每个重试启动一个新的十秒超时,可能会将原本十秒的操作变成长得多的操作。

选择适合运行时的时钟和取消机制,并在恢复执行后再次检查截止时间。尝试之间的时钟检查本身不会取消正在进行的请求。完整的实现需要调度检查和取消超出操作生命周期的工作。

理解超时机制

在浏览器中,AbortSignal.timeout 测量活动时间。当 worker 挂起或文档处于后向缓存时,该时间可能会暂停。不要将其描述为通用的墙钟截止时间。

如果 fetch 收到中止信号,它可以在该信号中止时被中断。组合信号并不能消除定义整体取消策略的必要性。本指南解释的是策略,而不是提供完整的重试库;计时器、响应体处理和清理必须由实际实现来处理。

决定哪些请求可以重试

HTTP 幂等性描述了重复相同请求的预期效果。安全方法如 GET 是幂等的,PUT 和 DELETE 也按其定义的语义是幂等的。这并不意味着每次重复都返回相同的状态,也不意味着特定的服务器实现是正确的。

不要自动重试每一个不成功的响应。永久验证错误不应进入与瞬态服务故障相同的策略。POST 和 PATCH 不能保证幂等,因此未知结果需要 API 的特定协调或重复数据删除契约。

在调度前解释 Retry-After

Retry-After 可以包含非负的秒数或 HTTP 日期。以秒为单位的延迟是在收到响应后测量的。HTTP 日期需要与当前时间进行比较,可能受时钟差异影响。缺失或格式错误的值不授权无限或立即重试。

以下是一个说明性的响应头片段,而不是观察到的响应或完整的服务器配置。它要求客户端等待 120 秒。如果该延迟无法 fit 进剩余的操作预算,则停止,而不是缩短请求的延迟并更早重试。

HTTP/1.1 503 Service Unavailable
Retry-After: 120

追踪一致的时间线

假设一个假设的操作在时间零点开始,截止时间为十秒。尝试 1 失败,选择的退避允许尝试 2 在三秒时开始。对于此示例,假设其 503 响应在同一时间收到,Retry-After: 120。

剩余七秒,但请求的等待是 120 秒。预期的决定是停止,原因如 retry_after_exceeds_deadline。不存在第三次尝试。这些是用于解释决定的构造值,而不是网络测试的测量值。

如果相同的假设响应改为请求三秒,等待到时间六将剩余四秒。只有当策略允许且其工作受这剩余四秒限制时,才可能进行另一次尝试;时间并不承诺请求会成功。

限制退避和尝试次数

当 API 允许重试且未提供可用的 Retry-After 值时,封顶的退避策略可以随时间分散尝试。抖动改变等待期,以避免同步客户端反复一起到达。将封顶、随机化和最大尝试次数定义为应用程序策略,而不是声称 HTTP 标准提供一个通用算法。

在睡眠前,检查所选等待是否留有足够时间进行有用的下一次尝试。当它不留有足够时间时停止。大的 Retry-After 值是放弃短操作的理由,而不是缩短服务器请求的等待并在其到期前重试的理由。

协调未知的写入结果

如果连接在写入请求可能已发送后消失,服务器可能已提交,即使客户端未收到回答。重复有副作用的 POST 可能创建第二个订单或收费。保持已确认成功、已确认失败和未知结果之间的区别。

文档化的状态端点或幂等性密钥契约可以帮助协调结果。仅根据该契约重用密钥,包括其有效载荷和保留规则。发送任意头并不使服务器重复数据删除请求,状态查找本身也不是发出第二次写入的许可。

记录每个决定的原因

有用的诊断信息包括方法、尝试次数、剩余预算、响应状态、解析的等待和停止原因。将凭证、授权头和敏感请求体排除在这些记录之外。

区分策略停止和传输故障,以便操作员知道预算是否耗尽、服务器是否要求更长的等待,或写入是否需要协调。然后根据 API 文档审查代表性的故障案例。说明性时间线建立算术,而不是已部署客户端的可靠性或性能。

检查清单

  • 一个操作预算涵盖所有尝试和等待。
  • 有效的 Retry-After 值不会被缩短以强制更早重试。
  • 可重试的方法和响应状态来自 API 契约。
  • 未知的写入结果会被协调,而不是盲目重复。
  • 运行时取消和敏感数据处理是明确的。

时间示例是假设性的。本指南不实现完整的重试客户端,也不声称浏览器活动时间取消能 enforced 每一个墙钟截止时间。正确的行为取决于运行时、服务器语义和应用程序契约。

参考来源

  1. MDN: Retry-After ↗
  2. MDN: idempotent methods ↗
  3. MDN: AbortSignal timeout ↗
返回顶部 ↑