第 19 / 23 篇

第 18 章:带着实验边界做生产设计

实验已经能在工作进程死亡以后找到下一步,但把它放到生产环境仍然需要一份新的系统设计。教学中可控的工具账本、公开开发凭据、单数据库实例与固定合同,在真实业务里都需要重新确定责任。最后一章把已经得到的证据当成设计起点,同时保留它没有覆盖的问题。

18.1 先陈述能够兑现的保证

当前实现覆盖一个经过审批的积分副作用节点。计划在应用准入后持久化,审批绑定指纹;领取使用行锁;租约、owner 和 fence 限制本地写入;HTTP 回执丢失或进程退出后进入 unknown;权威查询决定确认既有效果或在剩余预算内按原键重排。

这些保证依赖具体前提。工具必须真正按同键同意图去重,查询必须具有足够权威性,回执字段必须能验证,数据库必须保持所依赖的事务语义。下游若在提交后长时间查询不到,普通 404 就不再足以支持当前重排判断,需要不同的查询合同或更保守的等待策略。

非幂等工具未知时停留人工处置。取消后保留已完成效果,没有自动撤销。审批有效期限制派发许可,但代码没有独立的全局工作流截止时间。把这些边界写入对外合同,比把所有失败都承诺为“自动恢复”更接近可运维系统。

18.2 补齐身份和业务授权

实验中的 Actor 由可信应用传入;代码检查租户、角色和主体字段,却没有验证真实登录令牌。公开的工具 token 只为了演示 HTTP 边界。因此生产设计首先要说明身份如何认证、租户如何绑定、谁能批准哪些账户与额度,以及权限撤销如何传播。

模型只能提交有限业务提案。工具端点、凭据、能力和重试预算应来自受信任配置。生产工具还应独立检查业务对象归属,不能仅因为调用来自 worker 就接受任意账户。审批者也需要看到明确对象、数量、币种、目的与指纹对应的版本。

取消有时间边界:BeforeCall 检查后到网络调用之间,仍有无法用本地事务封住的窗口。如果业务要求撤销必须实时生效,需要提供者接受短期许可、独立授权检查或明确的提交协议。不能把本地多查一次数据库写成跨系统即时撤销保证。

18.3 对数据库与工具分别设计故障预算

工具和工作流在本实验共享一个 PostgreSQL 实例,只是各自提交独立事务。这足以制造“工具已提交,本地终态失败”的窗口,却没有演练两个数据库各自停机、复制延迟、网络分区、跨区域切换或提供者灾难恢复。

生产持久性要说明事务提交的存储前提、备份恢复目标、主从切换行为,以及恢复后会不会丢掉已经向用户确认的状态。工具幂等记录还要说明保留期限,期限之外的重放需要重新评估,不能永久继承旧键的安全性。

若提供者没有权威查询,但有异步回调,需要验证回调签名、防止重放,并把它与原业务键和指纹绑定。回调到达的顺序也可能与客户端错误、取消和租约回收交错。引入回调增加了一条事实来源,不会自动消除状态机竞争。

18.4 扩展到多个副作用要重新建模

单个积分节点没有补偿链、分支合并、子工作流和人工阶段间的复杂依赖。若要实现“扣库存、收款、发货”,不能把三次 HTTP 放进同一个函数,然后沿用单节点的 unknown 状态。未知的是哪一步,会决定下一步是否可以继续。

每个副作用都需要稳定身份、独立回执、执行前提和恢复判断。补偿也需要自己的业务授权与幂等键;退款成功不等于历史收款没有发生。跨步骤结果应表达事实与后续处理,而不是用一个 cancelled 抹掉整条业务历史。

当分支、定时器、版本路由、重放历史和运维需求持续增加时,应比较成熟工作流平台的模型与成本。选择平台仍需要理解工具副作用合同,平台无法替一个没有去重与核查能力的接口凭空证明恰好一次。

18.5 结课设计:一项需要人工批准的额度发放

请以一项企业积分发放为题,交付设计文档和可复现实验。业务上限由租户策略决定,审批有有效期,工具可能明确限流,也可能提交后丢响应。提交物应说明操作身份、计划修订、审批绑定、状态转移、预算单位、取消语义和版本处置。

实验至少包括两个真实 worker 竞争、领取后 SIGKILL、工具提交后 SIGKILL、无权威查询时的人工停留、终态事务失败,以及核查期间取消。每项结果同时检查工作流与提供者账本,并区分自然等待、SQL 边界注入和假设分析。不要把没有运行过的故障写入“已验证”清单。

评审时用本书的真实结果作参照:双进程竞争只出现一次领取和一次效果;after_claim 恢复消耗两次领取而只有一次 POST;after_tool 通过查询完成而不增加 POST;可信 429 在三次预算后 failed;未知空查询在预算耗尽后仍停 unknown。这些不同终态背后有不同证据,不能为了界面整齐强行合并。

18.6 让上线决策能够被复查

上线前的演练还应覆盖自己的真实提供者合同、连接与速率预算、审计权限、告警处置和恢复手册。实验源码和报告要固定版本,原始输出要能回溯到运行环境;同一次发布的制品应能与所验收的源码对应。绿色状态只有连到这些事实才有意义。

一次失败演练暴露的问题,应写成具体触发条件与修复后行为。例如“核查期间取消仍可能重排”,修复就是恢复事务锁行后重新读取消标记,再用真实竞争实验验证。不能只写“增强稳定性”,让下一位维护者重新猜测哪项不变量曾经失守。

这套方法的价值在于,让一个新执行者能够回答:原来批准了什么,外部已经发生了什么,现在还允许做什么。答案不足时,系统能够留下明确待核查状态,并把处置交给有证据、有权限的人。

练习。 为结课设计写一页上线评审。列出三项已有实验证据、三项尚未覆盖的生产前提,以及一项必须由业务负责人决定的取舍。最后为 unknown 超过一天设计处置流程,要求任何人工重放或补偿都保留原效果、证据、授权者和新的操作身份。