Skip to content

第 18 章 Chapter Outline:Retry、Recovery 与容错

章节契约

读者完成后的能力: 能将失败拆为可重试、需观察、需补偿、不可恢复或需人工升级的条件;能为一次尝试写出效果状态、上限、检查点和停止条件;能解释为什么“超时”“失败”和“未执行”不是同义词;能审查一个恢复策略是否会重复副作用或放大负载。

前置知识: 第 10、11、14、15、17 章。读者只需能理解 JavaScript 对象、状态表和 Mermaid 状态图。

章节边界: 不证明真实 Tool、HTTP、队列、浏览器、云服务或数据库动作是否可重试;不实现睡眠、指数退避、熔断器、恢复执行或补偿执行;不把教学输出当作真实故障处理结果。

小节蓝图

1. 失败不是一个状态:从失败文本到恢复决定

  • 读者问题: 为什么 timeoutpermission_deniedinvalid_input 和效果未知不能走同一条“重试”路径?
  • 叙述任务: 分开失败信号、效果状态、证据缺口和下一步决策。
  • 来源边界: 分类表是本书模型;REF-065 仅提供通信失败和幂等请求重试的协议语境。
  • 验证: 读者能指出“未读取到响应”不是“服务端没有执行”。

2. 有条件的重试:预算、上限、退避与单一所有者

  • 读者问题: 什么条件下可再发一次尝试,又如何避免一层层放大?
  • 叙述任务: 介绍可重复性、上限、重试预算、退避/随机化和单层所有者;把具体参数放到任务契约。
  • 来源边界: REF-066 只支持 Google SRE 的负载放大风险与建议;Recovery Contract 为本书模型。
  • 验证: 读者能拒绝“多层各重试三次”的无主策略。

3. 先观察还是先恢复:效果状态与检查点

  • 读者问题: 调用中断后,为什么不能默认重新执行?
  • 叙述任务: 使用 not_appliedappliedunknown;说明检查点保存的不是成功文本,而是可恢复所需的关联、状态、输入摘要和补偿信息。
  • 来源边界: 观察和状态术语沿用第 10、11、15 章;字段为本书模型。
  • 验证: unknown 进入 needs_observationescalate,不进入自动重试。

4. 恢复与补偿:修复有效状态,而非承诺回到过去

  • 读者问题: 已部分完成的多步骤任务如何选择恢复、补偿还是保留状态?
  • 叙述任务: 定义恢复 Runbook、补偿触发、不可逆点和人工决定。
  • 来源边界: REF-067 仅提供补偿事务的应用特定、可失败、需关联/进度/人工的背景。
  • 验证: 读者能解释为何“撤销”要有自己的幂等性与检查点。

5. 停止、熔断与人工升级:给失败留出口

  • 读者问题: 何时停止比继续尝试更可靠?
  • 叙述任务: 定义重试耗尽、不可重试错误、不可逆效果、证据缺口和补偿失败的出口;说明熔断是运行时策略,不是一个布尔值。
  • 来源边界: 停止/升级矩阵为本书模型;不实现真实断路器。
  • 验证: 读者能为每个出口说明需记录的证据和人类所需的下一步。

6. 完整工程案例:资料获取失败的受限研究 Agent

  • 读者问题: 如何在资料下载不稳定时避免编造内容或无限刷新?
  • 叙述任务: 构造教学场景:只读资料获取先检查来源、再在受限策略内重试;效果未知时观察;多次失败记录阻塞并交接;已写入的错误摘要只能在存在补偿契约时处理。
  • 来源边界: 文件名、来源、状态和结果均为教学对象,不表示网络请求或内容获取已发生。
  • 验证: 纯内存测试覆盖可重试、未知效果、补偿、缺检查点、不可逆和升级。

计划图示与示例

  • 图示: 失败分类先检查效果状态,再根据策略、上限、检查点和补偿能力输出 retryrecovercompensateneeds_observationstopescalate。所有节点都只表示本书教学决策。
  • 示例: assessRecoveryDecision 对注入的操作、失败、检查点和策略做确定性判定;它不等待、不重试、不写日志、不执行补偿或调用外部系统。

Outline 完成检查

  • [x] 覆盖错误分类、退避/预算、幂等性、检查点、补偿、停止和人工升级。
  • [x] 已将观察、评估和长期运行章节的责任分开。
  • [x] 已明确来源事实、本书模型和教学案例的边界。
  • [x] 已定义可观察的图示、代码与测试路径。

从同一套 Markdown 书稿生成。