“重传计时器为了修复传输缺口;应用deadline为了限制整个调用愿意等待多久。一个调用可以在TCP下一次重传之前就到达deadline;也可能经历多次TCP重传而仍在业务预算内。两者不应共用…”
形式陈述
deadline是调用方停止等待某个逻辑请求结果的截止点,timeout通常是某一步允许等待的时长。固定调用方单调时钟,起点
DNS、排队、建连、发送、等待响应、重试退避和再次尝试共享同一个D。若某一步自己的上限为C,其本地截止点取
执行器在启动新动作、定时器触发和处理完成回调时检查D;R=0就不再启动尝试,迟到响应不再被记为“在期限内成功”。若线程被长期暂停,代码不能保证恰在D那一瞬间运行;实际终止通知的延迟还取决于调度。这里的合同首先限制哪些动作和结果可被继续接纳。
单调时钟不会因墙钟校时直接倒退,适合本机经过时间;不同机器的单调时钟原点却不同,不能直接发送一个本机单调时间数让远端当自己的绝对deadline。传剩余时长可避免原点问题,但若接收方从收到时重新计满该时长,会多出网络传输时间。没有额外时钟或时延界时,本页只保证调用方仍以自己的D停止等待;远端收到的预算用于限制额外工作,不是严格同时停止的证明。
取消是通知及资源回收请求,不等于回滚。远端可能在取消到达前已完成效果,或需要在安全点才停止工作。deadline耗尽说明缺少及时可接受的结果,不证明业务没有执行。
直觉
总预算像旅行的最晚到达时间。换乘失败后可以重新规划,但不能把“最晚到达时间”每次都顺延十分钟。给每段单独设短超时,却让它们一段段重复,仍可能远超用户愿意等待的总时长。
预算还有用途差别:等得更久可能获得答案,但不能凭等待结束判定答案是什么。时间边界和业务结果边界应分别记录。
例子与边界
总预算1000毫秒,t0=0、D=1000。DNS用100,首次连接用200,到t=300;发送用50,到350;首次等待200,到550仍无响应。退避150,到700;重连100,到800;第二次发送50,到850,剩余150。即使第二次等待的局部上限是400,也必须在本地D=1000停止接纳及时结果,不能等到1250。
若重试调度器在t=1010才醒来,R=0,不再开始第三次请求。若第二次业务在t=900完成而响应t=1030才到,业务可能成功,但调用的及时结果仍已超时;在D时应按结果未知和后续查询合同处理。随后若取得完整、可信且匹配的结果,可更新后续业务状态,但不能把它改记为在原期限内成功。
跨机例中,A在自己的t=700发出“剩余300毫秒”,网络花40毫秒后B收到。B若从收到起算300,工作可能持续到A时间1040。传剩余时长解决的是时钟原点不一致,不自动扣掉未知的40毫秒。A仍在1000停止等待;若要求B也必在A的1000前停,需要额外时间同步误差界、传输上界或更强协议。
推论与应用
重试的退避可以减少同步碰撞,但也消耗同一预算。一次重试是否值得启动,既要看R>0,也要看操作语义是否允许重复,以及是否给连接和响应留下有意义的时间;后两项是策略,不能由正剩余时间自动推出。
并行分支共享D时,不能把每个分支预算加起来解释成总延迟;串行阶段则确实累积经过时间。监控应分开报告排队、解析、连接、服务和退避开销,才能知道预算在哪里耗尽。