Skip to content

Retry Policy

sungaowei edited this page Oct 16, 2026 · 2 revisions

重试策略 (Retry Policy)

English Version | 简体中文


网络重试在 SDK 中是默认开启的。typesafe.DefaultRetryPolicy() 返回如下默认配置:

字段 默认值 含义说明
MaxRetries 2 初始尝试失败后的最大重试次数。设为 0 则完全关闭重试。
BackoffInitial 500ms 首次退避等待延迟;后续每次尝试翻倍递增,直至 BackoffMax。设为 0 禁用退避。
BackoffMax 5s 单次退避等待延迟的上限上限。
BackoffJitter 0.25 随机抖动因子,在 [0, 1] 之间随机扣减退避时间,避免群集重试风暴。
HTTPStatuses 408, 429, 以及所有 5xx(含 529) 触发自动重试的 HTTP 状态码集合。由 DefaultRetryStatuses() 构建。
RespectRetryAfter true 是否严格遵守服务端的 retry-after-ms 与 Retry-After(秒数或 HTTP 时间)响应标头。
APIConnectionError true 是否对完全未收到 HTTP 响应的网络连接失败进行重试。
APITimeoutError true 是否对单次尝试发生超时的请求进行重试。
RetryErrors nil 额外触发重试的哨兵错误列表;使用 errors.Is 进行匹配。
Predicate nil 针对每次失败调用的自定义决策函数 func(error) bool;返回 true 即触发重试。
Timeout 30s (DefaultRetryBudget) 单次调用的总预算时间,覆盖初始尝试、各次重试与退避延迟。若下一次重试加上延迟将超过预算,则直接放弃重试并返回最后一次错误。设为 nil 禁用总预算。
Sleep nil 测试缝隙:用于注入自定义上下文感知定时器 func(ctx, delay) error。
RandFloat nil 测试缝隙:用于注入确定性的抖动伪随机源 func() float64。

自定义重试配置

可以从默认策略开始局部微调,或者按需创建全新策略:

policy := typesafe.DefaultRetryPolicy()
policy.MaxRetries = 4
policy.BackoffInitial = 250 * time.Millisecond
policy.Timeout = new(15 * time.Second) // 将整体调用预算设为 15s

client, err := typesafe.NewClient(typesafe.WithRetryPolicy(policy))

扩展业务重试规则

通过 RetryErrors 或 Predicate,可以轻松将重试决策扩展到外部业务错误:

policy := typesafe.DefaultRetryPolicy()
policy.RetryErrors = []error{myTransientErr}
policy.Predicate = func(err error) bool {
	return shouldRetryByCustomLogic(err)
}

核心行为与机制

  • 最大尝试次数:MaxRetries = N 意味着在整个生命周期内最多执行 N + 1 次网络尝试。
  • 指数退避与抖动:第 1 次重试等待 BackoffInitial;后续重试时间翻倍(受 BackoffMax 封顶),然后扣除 BackoffJitter 比例的随机抖动。所有延迟均精确取整至毫秒。
  • 服务端 Retry-After 优先:若 RespectRetryAfter 为 true 且响应携带有效的 retry-after-ms 或 Retry-After,SDK 将完全遵照服务端要求的等待时间休眠,不会再施加 BackoffMax 上限或抖动。
  • 总预算熔断:在设置了 Timeout 预算时,若计算出的下一次重试时刻会超出总预算,SDK 会立即终止重试流程并原样返回最后一次错误,防止无意义等待。
  • 上下文取消即终止:若请求的 context.Context 发生超时或被外部取消,重试流程会立即终止,绝不产生多余调用。
  • 全链路追踪:每次重试都会附带 X-TypeSafe-Retry-Count 请求头(第 1 次重试带 1,第 2 次重试带 2……)。调用方若传入该标头会被自动清洗。

其他辅助方法

err := policy.Validate()   // 校验重试配置参数是否合法
copy := policy.Clone()     // 深拷贝配置副本,适用于单次调用的细化定制
err = policy.Execute(ctx, func(attempt int) error {
	// 在该重试策略保护下执行任意操作
	return doSomething(attempt)
})

完全关闭重试

在需要断言单次请求行为的单元测试中,可将 MaxRetries 设置为 0:

policy := typesafe.DefaultRetryPolicy()
policy.MaxRetries = 0

Clone this wiki locally