超时设计是什么
超时设计为每一次跨进程调用设置时间上限,让失败尽快暴露而不是无限等待。阈值应覆盖正常耗时的高分位并留出余量;预算从端到端目标逐层扣减,上游超时大于下游预算之和,否则上游提前放弃时下游还在继续执行,资源被白白消耗。
容易漏掉的等待
除了建连与读响应,连接池等待、域名解析、TLS 握手、序列化以及重试累计耗时都在预算之内。只设置读超时而忽略取连接的排队时间,高峰期同样会长时间阻塞,而且监控上看不到慢调用,因为请求根本没到下游。
基本信息
| 原则 | 每个网络调用都要设超时,含连接与读写阶段 |
|---|---|
| 预算 | 按端到端预算逐层扣减,而非各层等值设置 |
| 姿势 | 超时后不再等待结果,同时要处理迟到的响应 |
| 迟到响应 | 下游可能已执行完成,需要幂等或对账兜底 |
端到端预算拆分
端到端预算拆分
总预算 800ms(用户可接受)
├─ 网关与鉴权 50ms
├─ 订单处理 300ms
│ ├─ 库存查询 100ms
│ ├─ 支付预授权 150ms
│ └─ 校验与本地计算 50ms
├─ 其他下游调用 350ms
└─ 缓冲 100ms
# 规则:下游超时设置小于上游剩余预算,逐层扣减各环节超时
| 环节 | 是否容易遗漏 | 说明 |
|---|---|---|
| 连接超时 | 否 | 建连阶段,通常设置得比读超时更短 |
| 读超时 | 否 | 等待响应阶段,按高分位加余量 |
| 连接池等待 | 是 | 池满时排队,需要单独设上限 |
| 域名解析与握手 | 是 | 首次调用或缓存失效时出现 |
| 重试累计时长 | 是 | 各次重试耗时之和不能超过上游预算 |
超时之后怎么办
超时只表示上游不再等待,不表示下游没有执行。写操作超时后必须能判断最终状态:靠幂等键查询、靠对账任务补偿,或让下游在超时后回写结果。读操作超时可以安全降级到缓存或返回默认值,写操作超时如果直接按失败处理,就会产生上游回滚、下游成功的状态分叉。
超时值应取自分位数据而不是平均值:平均值掩盖了长尾,按平均耗时设置的超时会在流量高峰大面积触发,表现为随机的接口失败。