标准答案
- 入口先根据用户体验和服务等级目标设定总 deadline,并把剩余时间传播给网关、下游 RPC、数据库和异步调用。
- 每一跳都应有连接、读取、执行和排队等局部超时,且不能超过上游剩余预算,否则上游已放弃后下游仍会继续堆积。
- 客户端断开或上游取消时,应尽可能传播取消信号,停止未开始的任务、查询或流式传输;已提交的关键业务需要明确是否继续完成和如何查询结果。
- 重试只适用于瞬时网络故障、明确可重试状态和具备幂等语义的操作;要限制次数、总时间和并发,并使用退避和抖动。
- 超时、取消和重试都需要记录原因、剩余预算和最终结果,才能判断是容量不足、依赖变慢还是策略配置冲突。
题目解析
只在最外层设置超时会造成内部请求继续占用连接、线程和数据库资源,最终把一个超时扩散成系统性排队。
重试会放大流量。下游已经过载时,更多同步重试通常比快速失败、限流和异步补偿更危险。
代码示例
下游调用应使用从上游 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 或取消机制。
- 对所有失败立即重试,包括参数错误、权限错误和非幂等写操作。
- 把客户端取消理解为业务一定没有执行。