标准答案

  1. 入口先根据用户体验和服务等级目标设定总 deadline,并把剩余时间传播给网关、下游 RPC、数据库和异步调用。
  2. 每一跳都应有连接、读取、执行和排队等局部超时,且不能超过上游剩余预算,否则上游已放弃后下游仍会继续堆积。
  3. 客户端断开或上游取消时,应尽可能传播取消信号,停止未开始的任务、查询或流式传输;已提交的关键业务需要明确是否继续完成和如何查询结果。
  4. 重试只适用于瞬时网络故障、明确可重试状态和具备幂等语义的操作;要限制次数、总时间和并发,并使用退避和抖动。
  5. 超时、取消和重试都需要记录原因、剩余预算和最终结果,才能判断是容量不足、依赖变慢还是策略配置冲突。

题目解析

只在最外层设置超时会造成内部请求继续占用连接、线程和数据库资源,最终把一个超时扩散成系统性排队。

重试会放大流量。下游已经过载时,更多同步重试通常比快速失败、限流和异步补偿更危险。

代码示例

下游调用应使用从上游 deadline 计算出的剩余时间,而不是各层独立设置更长的固定超时。

TypeScript
const remainingMs = deadlineAt - Date.now()
if (remainingMs <= 0) throw new Error("deadline exceeded")

const response = await inventoryClient.reserve(input, {
  timeoutMs: Math.min(remainingMs, 800),
  signal: requestAbortSignal
})

常见误区

  • 只配置网关超时,服务内部调用没有 deadline 或取消机制。
  • 对所有失败立即重试,包括参数错误、权限错误和非幂等写操作。
  • 把客户端取消理解为业务一定没有执行。

作者信息