先不要回滚,也不要继续叠加补丁。把日志按“请求进入—中间处理—响应返回”三段重新对齐时间戳,找出修复动作改变了哪一段的假设,再判断该保留、改写还是退出这次修复。多数“修好A、坏了B”的情况,不是修复本身错了,而是它顺带改动了一个被下游默认依赖的条件。
修复后出现的新异常,未必由修复引起。它可能一直存在,只是原先被旧问题掩盖;也可能是流量、缓存或上游策略在同一时段变化。要区分这两种情况,需要看三组证据:
如果新异常集中在修复未触及的路径上,优先怀疑环境变化而非修复本身。如果新异常恰好出现在修复覆盖的路径上,但状态码从一种错误换成另一种,说明依赖链被改动,进入下一步拆分。
修复通常只改一个环节,但每个环节都隐含对上游和下游的假设。拆链时不要按代码模块分,而按数据流分:
假设一次修复把某类请求从302重定向改为200直接返回。上游没问题,但下游的日志采集脚本仍按“302后跟一次目标请求”来配对,于是新异常表现为目标请求缺失、日志里出现孤立记录。此时依赖链断在“下游默认存在第二次请求”这一条,而不是修复逻辑本身。
保留适用于:新异常的影响面小于原问题,且下游可以同步调整。条件是你能定位到具体哪个下游假设被打破,并且该假设的修改不引入新的外部依赖。动作是列出所有消费旧输出的环节,逐一确认能否在同一窗口内更新。如果有一个环节无法同步更新,保留就会把问题推给更晚的环节。
改写适用于:修复方向正确,但输出形态需要兼容旧依赖。例如保留新逻辑,同时补回一个旧字段或旧重定向层,让下游按原假设继续工作。前提是兼容层不掩盖真实错误,且你能说清它何时可以移除。改写后要观察新异常是否消失、原问题是否复发,两者同时成立才说明兼容层有效。
退出适用于:新异常的严重程度高于原问题,或依赖链涉及无法快速协调的外部系统。退出不等于回滚到旧状态,而是回到修复前的行为并保留日志证据,先恢复可预测性。退出后下一步不是重做同一个修复,而是先补上对下游假设的显式约束,再选择更小的改动范围。
假设某路径修复前返回500,修复后返回200但页面主体为空。可以做一个受控对照:只对一小部分请求保留旧处理分支,其余走新分支,对比两组日志中的响应长度、后续请求数和错误码分布。若旧分支下下游请求正常、新分支下下游请求缺失,断点就在“下游依赖响应长度或内容标记”这一条。这个对照只用于定位,不用于长期分流;一旦断点确认,就应回到保留、改写或退出的取舍上,而不是让两套逻辑长期并存。
无论选择哪种处理,下一步的监测信号应来自被改动的依赖链环节,而不是整体流量。若断点在上游输入假设,就盯该输入的缺失率;若断点在下游输出假设,就盯下游消费方的解析失败或配对失败计数。只有当这个针对性信号回到修复前水平,同时原问题没有复发,才能认为依赖链已经重新闭合。否则继续拆分下一段,而不是扩大修复范围。