现场是这样的。新版模型上线做灰度,网关按 X-Canary 头分流 10%,上线一小时监控显示新版本承接了 92% 的流量,客户端 SDK 根本没带这个头。

中间走过弯路,把「内部服务调用透传时丢了自定义头」当成主因,改完现象没变。

真正麻烦的地方在于,几个原因的现象几乎一样。分流规则默认走新版本而不是旧版本;header 名大小写在不同网关层被改写;灰度比例按请求数算,重试请求被重复计入。

第一件事是统计入口请求里该头的覆盖率

python -c "print('canary header ratio')"

随后用 curl 模拟带与不带头两种请求

curl -s -o /dev/null -w "%{http_code}\n" https://api.example.com/v1/chat -H "X-Canary: 1" -d @req.json

然后把缺省路由改成稳定版并要求显式打标

kubectl patch virtualservice app --type merge -p '{"spec":{"http":[{"match":[{"headers":{"x-canary":{"exact":"1"}}}],"route":[{"destination":{"host":"app-v2"}}]},{"route":[{"destination":{"host":"app-v1"}}]}]}}'

灰度期间对比两版的错误率与延迟

python compare_metrics.py --window 1h --tag canary

怎么算真的好了,看的是同一批现象。无头请求全部回到稳定版,带 X-Canary 的请求稳定落在新版本,新版本流量占比回到 10% 附近,两版错误率均未抬升。

补一句。灰度规则要么白名单命中新版本,要么默认命中旧版本,写成缺省新版本等于直接全量,这个方向反了最难发现。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189