小流量灰度只能证明“被抽到的那部分请求符合预期”,不能证明全量发布安全。灰度流量通常来自有限的入口、有限的客户端和有限的路径组合,而全量发布后,旧链接、外部引用、大小写变体、带参数地址和不同抓取来源会同时涌入,例外往往出现在灰度样本根本没覆盖到的分支上。因此,灰度通过后正确的动作不是直接全量切换,而是先把灰度期间没有触发的重定向分支列出来,逐条判断是保留、改写还是退出。
灰度通常按比例分流,而重定向的例外很少按比例分布。它更可能集中在低频但真实存在的入口上:某个只在旧版页面里出现过的绝对地址、某个被第三方引用时多加了一层参数的链接、某个大小写与规范形式不一致的路径。这些入口在整体流量中占比极低,按比例抽样时几乎不会被选中,但全量发布后它们会全部生效。
判断灰度是否可信,可以看它是否覆盖了以下三类差异,而不是只看通过率:
只要这三类里有一类没覆盖,灰度通过就只能说明“已覆盖部分没问题”,不能推导出全量安全。
发现例外后,处理方式不是越严格越好,而是取决于这个例外对应的旧地址是否还有真实价值。
如果例外来自外部引用、历史内容或用户收藏,且这些引用短期内不会消失,保留一条指向新地址的重定向是合理的。前提是目标地址确实承载了等价内容,而不是把用户送到一个不相关的页面。保留的代价是长期维护一张映射表,好处是不必追着每个引用方去改。
如果例外暴露的是匹配规则过窄,比如只匹配了精确路径而漏掉了同前缀的变体,那么问题不在地址,而在规则。此时应改写规则,让它在不误伤其他路径的前提下覆盖这些变体。改写前要确认放宽匹配不会把本应返回其他状态的地址也卷进来,否则会把一个例外换成一批新例外。
如果旧地址既没有外部引用,也没有内容对应关系,继续保留重定向只会让映射表越来越长,还会掩盖真正需要清理的入口。退出的前提是先确认没有外部依赖,再让该地址返回明确的状态,而不是让它继续指向一个已经无关的目标。
假设某站把文章地址从带日期的形式改为不带日期的形式,灰度阶段只从首页和列表页点击进入,全部跳转正常,于是判断可以全量。全量发布后,外部引用里那些带查询参数的旧地址开始出现,其中一部分因为规则只匹配了纯路径而没有命中,落到了默认页。
这个例子里,灰度的结论没有错,错在把“主入口正常”当成了“所有入口正常”。修正动作是先抓取外部引用和站点地图里出现的旧地址形态,按是否带参数、是否带斜杠、大小写是否规范分组,再决定每组是保留一条规则、改写匹配条件,还是标记为无价值退出。分组之后,下一步才是重新灰度,而且这次灰度要按形态分组抽样,而不是按总流量比例抽样。
灰度通过后,至少应完成三件事:列出灰度未覆盖的地址形态、对每种形态给出保留或改写的决定、把决定写回规则并重新验证。验证时看的不是单一指标,而是这批形态是否都能到达预期目标。
还要注意,某些现象不能单独证明处理正确。抓取量或请求量下降,既可能是例外被正确收敛,也可能是抓取方暂时减少了访问,还可能是规则把正常入口一并挡掉了;重定向状态码返回正常,也不代表目标内容等价。robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录,这些都需要在判断例外时分别核查,而不是用一个信号代替全部结论。
最终取舍应落在“这条旧地址是否还有真实使用者”上:有稳定引用就保留并维护映射,规则写错就改写匹配,确认无价值再退出。把灰度当成一次抽样检查而不是全量保证,才能在发布后少遇到意外分支。