第 6 章:超时、取消和业务撤销是三件事
用户关闭页面后,入口连接消失了。服务器是否立刻知道,取决于连接状态和下一次读写;上游是否停止计算,还取决于它的实现。即使所有连接都关闭,已经执行的工具动作和已经产生的费用也不会自动消失。
6.1 用期限管理一整次请求
只设置单次读取超时,可能让一条每隔几秒发送一个字节的流持续占据资源。只设置总超时,又可能让正常长回答被粗暴切断。实用的时间策略通常同时包含建连期限、首事件期限、读取空闲期限、写入期限和请求总期限。
这些期限不是可以直接相加的独立预算。假设入口最多允许 30 秒,路由和等待已用去 8 秒,后续尝试就不能重新获得完整 30 秒。应以单调时钟记录剩余时间,向下游依赖传播或转换,而不是每层重置一个新的计时器。
Envoy 的 route timeout、idle timeout 和 per-try timeout 有不同作用。接入时应阅读所用版本的文档,确认计时起点与是否覆盖流式场景。照搬一个名为 timeout 的配置值,不足以说明整个链路的行为。
6.2 客户端退出是一种观测,不是一份结算单
服务器发现写入失败,能说明这条连接无法继续按原方式交付。它不能据此判断客户端到底看到了多少内容,也不能把实际用量改成零。对于可能计费的上游,缺少可靠终止记录时仍需保留待核查状态。
有些系统支持显式取消接口。它使客户端不用等待操作系统发现断开,就能表达取消意图。取消接口同样需要认证,并验证调用者有权取消该运行,防止一个租户使用猜到的标识终止另一个租户的任务。
6.3 实验中的取消范围
随书网关提供 DELETE /v1/runs/<request_id>。它按租户识别运行,将取消意图传给工作线程,并尝试关闭上游连接。本地替身会观察连接终止,测试能检查它在受控窗口内停止发送。
这个证据说明实验里的取消传播生效。它不等于远程供应商退款,也不等于工具系统回滚。接入真实服务时,需要确认是否存在供应商取消 API、取消请求是否被接受,以及取消后仍可能产生哪些费用。
6.4 释放资源要按类别分别处理
运行停止后,并发槽位应有可靠的 finally 清理路径;连接和线程也要退出。预算则取决于处理证据。明确尚未执行的拒绝可以释放预留,执行状态未知的中断不能沿用同一个释放规则。
| 资源或状态 | 停止请求后的处理依据 |
|---|---|
| 本地并发槽位 | 本地工作确实结束,且只释放一次 |
| 本地网络连接 | 已关闭或进入受控清理路径 |
| 预算预留 | 可信用量、明确未开始,或进入未知核查 |
| 业务副作用 | 外部业务记录与补偿协议 |
练习。 取消请求与上游 done 事件几乎同时到达。你会使用哪个受保护状态作为结算依据?请写出一个能接受的线性化顺序,并说明怎样避免重复释放。