先把当时的情况摆出来。分流逻辑写的是 user_id 对 100 取模小于 10 走新版,灰度比例从 10% 调到 20% 后又加了两台实例,用户反馈同一个账号刷新几次答案风格来回变。

真正麻烦的地方在于,几个原因的现象几乎一样。取模的基数跟着实例数变了,映射关系整体错位。也可能是分流在网关和业务层各做了一次,两次结果不同。

还有一种情况,用户 id 在部分接口是字符串,取模前没统一类型。另外,比例调整直接改了阈值,没有固定分桶。

先打印同一 id 两次分流的落点

python -c "print([(u, hash('u'+u)%100) for u in ['10086','10087']])"

然后改成固定 1000 桶并按桶灰度

python -c "print({'buckets':1000,'gray':200,'bucket':hash('u10086')%1000})"

只在一层做决策并把结果透传

python -c "print({'decide_at':'gateway','header':'x-exp-group'})"

调比例后回放 1000 个真实 id 校验

python -c "import random;print(sum(1 for _ in range(1000) if random.random()<0.2))"

怎么算真的好了,看的是同一批现象。同一 id 连续十次请求都落在同一组,比例调整后老用户的归属不变,两组流量占比与设定值相差不到 1%。

这里还有个坑。分桶要对固定基数取模并做哈希,实例数、副本数都不能进入公式,否则每次扩容都是一次重洗。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189