跳到主要内容

超时与重试

如何设置 unary 调用的时间边界?​

配置文档默认值控制对象
ConnectTimeout50ms建立新连接
RPCTimeout0,不限时Client 等待一次 RPC
ReadWriteTimeout5sServer 网络读写等待
ExitWaitTime5sServer 退出等待
  • 本地预算: 显式设置 RPCTimeout;Client 的 context 更早到期时会提前返回,超时默认不重试;
  • Handler: 读写超时不限制业务执行;业务和数据库仍要主动遵守 context;
  • 跨进程: 非 streaming 默认不把 RPC 超时写入 Server context;Thrift 使用 TTHeader、两端 TTHeader MetaHandler 和 Client RPCTimeout,并在 Server 设置 WithEnableContextTimeout(true)(v0.9.0+);
  • 取消边界: 传递超时预算不等于远端能立即观察调用方手动 cancel;不得把本地返回当作远端写入已撤销;
  • 错误识别: kerrors.IsTimeoutError 分类超时;细分业务取消/业务 deadline 需显式启用框架的细粒度错误码;

如何配置失败重试?​

  • Failure Retry: 超时或指定错误/响应后再次调用;
  • Backup Request: 超过延迟阈值并发发送备用请求,先成功者获胜;
  • Mixed Retry: 组合 failure 与 backup 策略;
  • 建连失败重试: 请求尚未发出时的框架机制;
policy := retry.NewFailurePolicy()
policy.WithMaxRetryTimes(2)
policy.WithMaxDurationMS(800)

cli, err := userservice.NewClient(
"user",
client.WithRPCTimeout(300*time.Millisecond),
client.WithFailureRetry(policy),
)

如何约束重试的副作用?​

  • 幂等: 开启业务请求重试的首要前提;
  • 总预算: 首次调用 + 退避 + 所有重试必须小于上游 deadline;
  • 放大: 重试会增加下游流量; 故障时需要停止策略与熔断保护;
  • 同节点: 默认优先换实例; 只有明确场景才启用 same-node retry;
  • streaming: 不支持常规重试;
  • backup: 延迟阈值参考 TP99; 过小会长期制造双倍请求;

如何选择恢复策略?​

  • 快速失败: 非幂等写、资源已耗尽、明确业务异常;
  • Failure Retry: 幂等且瞬时网络/实例错误可恢复;
  • Backup Request: 长尾延迟主导且下游容量充足;
  • 不确定时: 先设置 timeout 与观测,不开启重试;