背景
依赖变慢时每层都重试三次,原本一次请求可能被放大成几十次。重试需要全链路预算,而不是固定循环次数。
核心判断
- 仅重试明确的暂时失败,并确认操作幂等。
- 退避加入随机抖动,同时受入口 deadline 限制。
- 只在一层负责重试,记录尝试次数与预算耗尽。
最小示例
下面保留核心逻辑;业务类型、调用入口和环境配置按项目补齐。
var lastErr error
for attempt := 0; attempt < 3; attempt++ {
if err := ctx.Err(); err != nil {
return err
}
lastErr = call(ctx)
if lastErr == nil || !retryable(lastErr) {
return lastErr
}
if attempt < 2 {
if err := sleep(ctx, backoff(attempt)); err != nil {
return err
}
}
}
return lastErr
边界与误区
示例中 call、retryable、sleep 和 backoff 是业务适配函数,sleep 必须响应取消。最后一次失败后不再等待,错误要保留最后一次调用结果。
验证方式
注入超时、永久拒绝和短暂故障,核对实际调用数;多实例同时失败时,检查抖动是否减少同步重试峰值。
小结
以请求 deadline 为总边界,对不可重试错误立即返回,并限制链路放大倍数。