上线那天,「完成」这个词最容易被用坏

2026-09-24 Aryee 3

改造项目的「完成」被用坏了。最常见的用法是:流量切到 100%,于是宣布完成。

这个跳跃里丢了两件事——改前改后一致这件事有没有证据,以及这套新东西是否已经有人能长期负责。前者丢了,问题会在几周后的某个业务周期里出现;后者丢了,半年后没人敢动它,于是它变成下一个待改造的遗留系统。

我的验收标准是五关,每一关都要有能被别人独立核对的证据。缺证据不算通过,只有开发自己看得懂的证据也不算。

验收要过的五关

哪一关 要回答什么 拿什么当证据 谁能核对 最常见的糊法
功能等价 采样窗口内每一条新旧输出的差异都找到了原因,并给出了结论 差异报表 + 每条差异的处置结论 业务方 拿「测试通过」替代真实输入比对
数据一致 对账跑满一个完整业务周期,差异降到零 逐日差异条数曲线,附上差异是按什么算的 财务/结算 只比行数,不比字段
性能不劣化 尾部不越过基线波动带,且峰值水位下不塌 同期对比的分位数报表 SRE 拿均值、跨期对比
可观测可运维 告警、日志、链路、runbook 全部指向新实现 一次真实值班处置记录 值班的人 把老监控项照抄成新监控项
组织接管 陌生工程师能独立完成一次小改动 由非改造成员提交的一次变更 接手团队 「我给你们讲一遍」

第三列是关键。每一层都必须有一个不是改造方的核对人。 这五关全由开发自己评的项目,等于没有验收——因为开发能判断的只有第一关的一部分。

「改前改后一样吗」这一关,两个要争的点

要给每一条差异一个结论,而不是要求差异数为零。 真实系统里新旧输出有差异往往是正常的(浮点顺序、时间戳精度、排序不稳定项)。规则是:每一条差异要么归到「已知且可接受」并写明理由,要么归到「必须修」。留一条「先不管」,验收就不成立。

覆盖度要说清是按什么算的。「覆盖了 90% 的请求量」和「覆盖了全部业务形态」是两件完全不同的事。前者按流量加权,会被高频简单场景填满;后者要按等价类枚举。改造验收要以后者为主,前者只用来估计影响面。两个数字都要报,只报一个就是在挑好看的。

性能基线的取法(这一层最容易做错)

改造后性能达标,标准比想象中严:

  • 同期对比,不跨期。 拿改造前的周一上午对改造后的周一上午。跨期对比里,业务量结构变化会盖过架构差异——你无法知道那个 P99 改善是你的功劳还是那天没什么人用。
  • 看分位数和尾部,不看均值。 均值被大量轻请求拉平。至少要 P95/P99,且必须分接口看;混在一起算,高频的轻接口会把低频的重接口盖住。
  • 冷启动失真要从窗口里剔除。 缓存预热、连接池建立、解释执行到编译的爬坡,会让切换后第一个小时明显偏差。观察窗口的起点应该在这之后,或者干脆把首小时单独列一档。
  • 峰值水位必须单独压。 这是最容易省的一条:资源利用率越高,同等配置的尾部延迟越差,而且是非线性的。 所以「机器少了 30% 但平均耗时持平」并不是结论——它意味着水位上去了,一次流量尖峰的后果和以前不是一回事。改造如果带缩量,就必须在目标水位下重压一次,看的是水位之上还剩多少余量。

于是这一层要的不是「持平」,是两句:尾部不越过基线波动带,且在预期峰值水位下余量不小于改造前。 后半句经常被忘掉,因为它的代价要到某次大促才显现。

可观测这层:抄监控项不算迁移

告警规则从旧系统复制到新系统,只是把名字改了。真正的标准是:有一次真实的处置记录,是在新实现上完成定位的——值班的人按新日志、新指标、新链路,把一次异常查到具体代码位置。

这条之所以硬,是因为它同时测了三件事:埋点够不够、指标的算法对不对得上、文档能不能用。三样里任何一样缺,处置记录就写不出来。

顺带一个具体检查:日志与链路里的业务标识必须还在。 改造期最常见的可观测退化是「错误能看见,但不知道是哪一笔」。这类问题在事故当时才发现,代价是当场补日志再重跑一遍。

组织接管:owner 唯一才算有 owner

「这个新服务谁负责?」——如果答案需要犹豫,或者出现两个团队各说一半,那它没有 owner。

标准我只用一条:由没参与改造的人提交一次真实的小改动并上线。 大重构不需要,那测不出接管;就是改个字段、加一条校验这种量级。走完这一条,说明文档、测试、发布通道、权限四样都是通的。任何一样不通,这个人会来找你,那就是验收不通过的证据。

旧代码什么时候才允许真删

这一段是我见过被跳过最多的。改造做完、流量切干净,很多人就直接把旧代码删了——然后两周后被一个"它怎么还在用"的电话叫回去。

删除前的六个前置条件:

  1. 无流量证据窗口覆盖最长的业务周期。 不是连续三天没调用,是覆盖到那些季度性、年度性的任务。窗口长度按本次涉及的最长周期取。
  2. 引用面搜索不能只搜代码。 要包含配置、调度任务、SQL 脚本、视图与存储过程、权限与白名单、外部对接方的集成配置。老系统改造:先证明能改,再谈怎么改 里那五样没写在文档上的约定,在这里全部要用上。
  3. 依赖它的周边资产先迁完。 备份策略、监控项、告警订阅、数据同步任务、报表取数。这些归运维和数据,不归开发,没人提醒你。
  4. 分两步删:先停用观察,再清除。 第一步把入口彻底断掉但代码与库表还在(可快速恢复),第二步才真的移除。中间留出至少一个业务周期。
  5. 删除动作的验收人必须是运维。 他们管备份、权限、监控和容量,只有他们能说清"删掉之后少了一份保障"这种事。开发自己批的删除,等于没有复核。
  6. 临时兼容层要有到期日。 所有「为了这次改造加的适配」都要登记归属与到期时间。没登记的东西不会被删——它会被下一代人当成"系统本来就这样"。

第 4 条值得多说一句:停用和清除之间的那个观察期,是整个退役过程唯一的安全带。 一次做完的人,本质上是在赌第 1、2 条查全了。这两条恰好是最容易查漏的。

验收签字到底签什么

签的不是「我信任这个团队」,是「我已经看到这一层的证据」。所以签字单要按层来,五层五行,每行一个核对人和一份证据链接。

同时,签字单上必须有一栏**「签完之后仍然没做的事」**。改造结束后总有已知未修的差异、被推迟的清理、临时兼容层。这一栏空着的项目,我不认为它是真做完了——更可能是没人列出来。

一点收尾

五层里,前两层的缺失会立刻暴露(业务方会来找你),后三层不会。

性能水位、可观测、接管能力这三样,都是延后才付账的,付账形式分别是一次大促抖动、一次查不下去的事故、一次没人敢改的追加需求。也正因为账是延后付的,验收时被省掉的通常是它们。

至于退役——它连验收单都上不去,所以最稳的做法是把它写成批次:「删除旧订单模块」作为一个批次,带它自己的证据和回滚方案。批次里的事会被跟踪,备注里的事不会。

你手上那套系统,卡在哪一步?

留个手机号和方便的时间,我打过来先听你说现状与约束,再给可执行的判断:这套系统是该继续修、该动哪里,还是干脆重做一版设计更省。

约一次沟通不接纯 UI 外包,只做系统层面的问题。