超时
超时限制等待时长,deadline 表示请求截止时刻。本文负责预算分配、跨层传播和取消。
1. 面试核心
先记住这几条,再读正文- 总预算与阶段上限。 每层调用使用剩余总预算与本地阶段上限中的较小值。卡 · 总预算
- 超时阶段。 连接池等待、建连和读超时约束不同阶段。
- 串行与并行。 串行调用逐次消耗预算,并行调用共享剩余截止时间。卡 · 串行与并行预算
- 取消语义。 取消是协作信号,已提交事务仍保留其结果。
- 截止时间传播。 gRPC 通过扣除已耗时间的 timeout 传播 deadline。
2. 总预算
入口按 SLO 与调用方容忍度确定总时限。预算包含网关、排队、下游、序列化和返回。
下游开始前,扣除已耗时间并预留收尾时间。重试与退避也消耗同一预算。阶段上限可以更短,避免单个步骤占满全部时间。
3. 超时类型
各阶段需要独立观察:
- 连接池获取有等待上限。
- DNS、TCP 与 TLS 有建立耗时。
- 请求写入与响应读取有等待边界。
- 数据库语句与事务有执行时限。
- 排队与整个调用有总时限。
socket read timeout 只覆盖相应读取等待。持续收到零星数据时,部分实现会反复重置读等待。总 deadline 负责限制整个调用。
4. deadline 传播
gRPC 将截止时间转换为扣除已耗时间的 timeout。接收方在本地建立剩余时限,降低跨主机时钟偏差影响。
Java 与 Go 的 gRPC 支持默认传播。应用仍需在正确的请求上下文中发起下游调用。自建 HTTP header 方案应明确单位、可信来源和上限。
预算耗尽时,拒绝开始新的业务工作。需脱离请求执行的任务应显式持久化,并返回任务 ID。
5. 取消传播
调用方结束等待后,服务端代码需响应取消。取消应覆盖队列任务、子 RPC 和并行任务。
Java interrupt 是协作信号。阻塞库和循环代码需检查并处理它。捕获 InterruptedException 后,可结束任务或恢复中断状态。
数据库驱动的取消能力依实现而异。已提交事务与外部副作用仍需查询或补偿。
6. 超时值
超时初值来自依赖延迟分布与允许的误超时率。过短会误判长尾,过长会增加占用。
建连、TLS 和冷启动需单独测量。连接复用后的延迟无法覆盖这些阶段。上线前用目标流量与发布场景校准。
7. 服务端上限
服务端独立设置最大执行时长。来自调用方的时限再短,也以更早的截止为准。
阶段超时与总时限共同生效。服务端上限保护容量,调用方预算表达请求的剩余价值。
8. 取消与故障指标
指标区分 deadline exceeded、主动取消与依赖失败。记录进入时预算、排队时间和各阶段耗时。
超时后继续运行的任务需独立计数。下游的客户端取消可由上游正常超时触发。取消突增时,再检查链路延迟与预算设置。
9. 串行与并行预算
设总预算 800 ms,当前已耗 100 ms。预留返回时间 50 ms,可用于下游的时间为 650 ms。
串行调用 A 的本地上限为 300 ms。A 实际耗时 200 ms 后,B 剩余可用 450 ms。B 再与自己的本地上限取较小值。
并行调用 A、B 时,两者可共享当前剩余截止时间。总等待由关键路径决定,而非把两者耗时相加。请求结束时取消尚未完成的子任务。
时限检查与资源清理应覆盖每次重试。算术预算还需预留实际调度和网络开销。
10. 常见问题
10.2 Future 超时与任务结束
Future.get(timeout) 超时只结束当前等待。需要停止任务时,还需发出取消请求。cancel(true) 尝试中断执行线程,任务仍需响应中断。
11 · 面试题卡片
本页题目与参考回答
11.1 多级服务调用如何设置超时并传播取消
出现公司:字节跳动
考察重点
- 理解timeout 与端到端 deadline 的区别。
- 理解阶段预算、剩余时间和取消传播。
- 理解已提交副作用与可取消任务的边界。
参考回答
各层使用剩余 deadline,并叠加更短的阶段上限。
当前层先扣除已耗时间与必要收尾时间。连接池、建连、读取和重试都在总预算内完成。
请求结束后传播取消,队列与执行代码负责响应。Java Future 超时本身只结束等待。已提交事务仍需按业务状态核对。指标区分主动取消、预算耗尽与依赖故障。
11.2 800 ms 总预算下,串行与并行下游怎样分配时间?
出现公司:暂无已核验的公开来源(本站自测)
考察重点:剩余预算、阶段上限与关键路径。
相关内容:串行与并行预算。
参考回答
串行调用扣除已耗时间,并行调用共享剩余截止时间。
已耗 100 ms 且预留 50 ms 时,下游共剩 650 ms。A 串行耗时 200 ms 后,B 最多使用 450 ms。各次调用还需与自身阶段上限取较小值。