永久重定向小流量灰度如何暴露全量发布的例外

📍 WDQWDWQD987AAAAA:216.73.216.124
📱 Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
🔗 /19fe28b01e8f.html
📄

永久重定向小流量灰度如何暴露全量发布的例外

小流量灰度能验证永久重定向在常规路径上是否生效,但无法覆盖全量发布后才会出现的例外:带参数的历史 URL、大小写变体、被 CDN 缓存的旧响应、以及只在特定地区或特定爬虫 UA 下触发的规则顺序问题。灰度阶段跳转正常,全量后出现 200 或 404,通常不是重定向本身失效,而是灰度样本没有命中这些分支。

矛盾现象:灰度全绿,全量后旧链接却返回 200

灰度期间抽检的 URL 全部返回 301,日志里也看不到异常。全量切换后,部分旧链接却直接返回 200,内容还是旧页面;另一些返回 404。两种结果指向完全不同的原因。

第一种解释是重定向规则确实生效,但旧页面仍可访问,说明源站还保留着旧路径的实体文件或旧路由,服务器在重定向之前就先命中了静态资源或应用路由。第二种解释是重定向规则没有命中这批 URL,原因是它们带有灰度样本中没有的查询串、末尾斜杠、大小写组合,或者被边缘缓存提前返回。

区分两种解释的证据:看响应头与命中顺序

要区分是“规则没命中”还是“旧内容还在”,不能只看状态码,要看响应头和请求路径的对应关系。

一个可操作的验证动作:从灰度样本之外,按“带参数、大写路径、末尾斜杠、深层子路径”四类各取若干旧 URL,用同一请求头分别请求,记录状态码与 Location。如果只有其中一类异常,就能把范围收敛到规则匹配条件,而不是全站重定向失效。这个结果直接决定下一步是改规则还是清理旧内容。

全量发布后必须单独验证的几类例外

带查询串的历史 URL

很多重定向规则只匹配路径,查询串被保留或丢弃的行为在不同配置下不一致。灰度若只测了无参数 URL,全量后带参数的旧链接可能既不跳转也不报错,而是返回旧内容。验证时要明确查询串是保留、丢弃还是参与匹配。

大小写与末尾斜杠变体

服务器对路径大小写的处理、以及是否把 /old 与 /old/ 视为同一路径,取决于具体配置。灰度样本若恰好都是小写无斜杠形式,全量后其他变体就可能落到默认路由上,返回 200 或 404。

边缘缓存与 TTL

旧 URL 在 CDN 或反向代理上可能仍有缓存副本。灰度期间请求量小,缓存未必被命中;全量后真实流量触发缓存,直接返回旧的 200 响应,重定向规则没有机会执行。判断依据是响应头中的缓存命中标识,以及清除缓存后同一 URL 是否恢复 301。

这里要注意:抓取量或请求量归零、或某个统计指标下降,并不能单独证明重定向处理正确。它也可能来自爬虫调度变化、站点地图未更新、或临时网络波动。需要结合响应头和实际跳转链一起看。

两种做法的取舍:先清理旧内容,还是先收紧规则

面对全量后的例外,常见两种选择,适用条件不同。

  1. 先清理旧内容:适合确认旧路径仍有实体文件或应用路由、且这些内容不应再被访问的情况。代价是清理范围可能影响其他仍在使用的路径,需要先确认依赖关系。动作是移除或下线旧路由,结果是重定向规则成为唯一入口,后续验证只需看规则是否命中。
  2. 先收紧重定向规则:适合旧内容必须保留、但对外应统一跳转的情况。代价是规则变复杂,匹配条件越多,越容易与后续新增路径冲突。动作是把匹配从路径扩展到包含大小写、斜杠和查询串的组合,结果是灰度样本需要同步扩充,否则仍会漏掉新例外。

选择依据是:旧内容是“不该存在”还是“该存在但不该被直接访问”。前者清理,后者收紧规则。两者都做时,先清理再收紧,可以避免规则去匹配已经不存在的内容,减少误判。

灰度设计上要补的一步

灰度要暴露全量例外,样本就不能只取“最正常”的 URL。把旧 URL 按参数、大小写、斜杠、层级、来源渠道分组,每组至少覆盖一条,并记录请求时的缓存状态。这样全量发布后出现的异常,能直接对应到某个分组,而不是重新从零排查。永久重定向的正确性不取决于跳转本身写没写对,而取决于它是否覆盖了全量流量里真实存在的 URL 形态。

图1 图2

nginx