Timeout Control
解释服务与 Agent Runtime 如何用 deadline budget、分层 timeout 和 cancellation 防止远程依赖、工具或整个任务无限占用时间与资源。
#concept
#growing
#backend
#ai
#reliability
[!info] related notes
Timeout Control
[!abstract] 一句话定义 Timeout 给一次等待设置最大时长;Deadline 给整条调用链设置绝对截止时间。它们把“可能永远等待”变成可处理失败,但只有配合 Cancellation、资源清理和错误分类,才真正终止无用工作。
Timeout 与 Deadline
Timeout = 从现在起最多等 2s
Deadline = 必须在 12:00:05 前完成
跨多层调用时优先传播 Deadline:
Client budget: 5s
→ Gateway spent 0.5s
→ Service receives remaining 4.5s
→ DB / LLM / Tool each gets a sub-budget
如果每层重新给完整 5s,实际端到端延迟可能远超用户预算。本进程计算剩余时间宜用单调时钟;跨进程不直接传本机单调时钟读数,需使用约定的截止时间/剩余预算协议并考虑传输耗时与时钟偏差。
分层时间预算
一次请求可能包含:
DNS / connect
→ TLS handshake
→ request write
→ response headers / first byte
→ body / stream idle
→ total operation
不同阶段的故障含义不同,因此不能只用一个模糊的“请求超时”。常见层次:
- Connect Timeout;
- TLS Handshake Timeout;
- Response Header / First Token Timeout;
- Idle / Read Timeout;
- Per-step Timeout;
- Overall Deadline。
Timeout 发生后,工作可能仍在继续
caller times out
→ returns error
→ downstream SQL / LLM / job still running
→ resources and side effects continue
因此下游必须:
- 接受并传播 Cancellation;
- 在 I/O、循环和工具边界检查取消;
- 释放连接、锁、临时文件和并发槽位;
- 对不可取消副作用记录“结果未知”,随后 Reconcile。
[!warning] Timeout 不代表操作失败 超时只说明调用方没有及时得到确定结果。远端可能没执行、正在执行,或已经成功但响应丢失。对写操作不能盲目重试。
Timeout 与 Retry
Timeout
→ outcome may be unknown
→ classify operation and error
→ confirm state or use idempotency
→ retry only within remaining budget
单次 Timeout 不能等于总 Deadline。若每次调用 30s、首次之外再重试 3 次,四次调用可累计 120s,还不包括 Backoff;总 Deadline 应进一步限制它。
长任务什么时候转异步
当任务天然需要几十秒到数分钟时,不应无限扩大 HTTP Timeout。更合理:
POST /jobs
→ validate + persist + enqueue
→ 202 Accepted + task_id
→ poll / SSE / webhook for status
这样客户端断线不等于任务丢失,服务也能独立管理取消、重试和恢复。
Agent Runtime 的时间边界
可分为:
- Run Deadline;
- Step Timeout;
- Model Connect / First Token / Total Timeout;
- Tool Timeout;
- Approval Expiry;
- Stream Idle Timeout。
每个 Timeout 都应产生结构化 Event / Trace,并明确 Run 是 Failed、Interrupted、Retrying 还是 Outcome Unknown。
设计检查表
- 端到端 Deadline 由入口创建并向下传播。
- 每个依赖有合理的 Connect、Read / Idle 和 Total Timeout。
- Timeout 后 Cancellation 能到达实际工作单元。
- 资源在 Success、Error、Cancel 三条路径都释放。
- 写操作超时后先 Reconcile 或使用 Idempotency Key。
- Retry 使用剩余预算,不重新获得完整时间。
- 长任务使用异步 Job,而不是无限增加 HTTP Timeout。
- 指标区分 connect、first byte/token、idle 和 total timeout。