配置灰度命中规则如何设计?
简化版
灰度命中规则要稳定、可解释、可复现和互斥。 实例级参数按稳定实例身份命中,用户或租户级规则按 userId/tenantId 确定性哈希。 规则需固定优先级、版本和盐,并保存目标快照,防止扩缩容或规则冲突造成漂移。
详细版
先确定生效粒度:配置在启动时按实例加载,就不能声称按请求用户灰度。 百分比可计算 hash(salt + subjectId) mod 10000 小于 threshold,万分桶方便平滑扩量。
紧急排除、显式白名单、标签规则、百分比和默认版本按固定优先级匹配。 服务端返回命中规则 ID 与期望版本,客户端上报实际版本。 规则变更本身也要审批、预览和审计。
完整版教学
一、先确定灰度粒度
实例级配置适合线程池、连接池和 JVM 参数。 用户级配置要求应用同时持有新旧规则并在请求路径选择。 租户级配置应让同一租户的相关请求保持一致。
命中粒度必须与配置实际读取粒度一致,否则精细规则也不会生效。
二、确定性哈希
bucket = unsigned_hash(salt + ":" + subjectId) mod 10000
hit = bucket < threshold
阈值 100 约为 1%,2500 约为 25%。 固定盐和算法后,从 1% 扩到 5% 时原 1% 仍保留。 哈希提供近似比例,小样本不会精确等于目标百分比。
三、主体键如何选择
用户体验选 userId,B2B 业务选 tenantId,基础设施参数选 instanceId。 不要使用时间戳、随机数或频繁变化的 IP。 匿名用户可使用持久匿名 ID,但清理 Cookie 后会重新分桶。 涉及数据一致性的流程要让同一业务实体始终走同一路径。
四、优先级和冲突
| 优先级 | 规则 | 用途 |
|---|---|---|
| 1 | 紧急排除 | 快速止损 |
| 2 | 显式灰度名单 | 定点验证 |
| 3 | 租户或标签 | 场景灰度 |
| 4 | 哈希百分比 | 扩量 |
| 5 | 默认版本 | 兜底 |
同优先级不能产生两个不同目标版本,发布前必须检测冲突。
五、版本化与可解释性
规则记录 ruleId、版本、主体字段、算法、盐、阈值、优先级和有效期。 每次决策能返回 ruleId 与发布版本,排障时才能复现。 规则保存不可变历史,禁止原地覆盖导致旧日志无法解释。 临时名单自动过期,防止永久遗留。
六、扩缩容与身份
用 Pod IP 命中会在重建后漂移。 实例灰度使用稳定身份,或冻结本轮目标快照。 目标实例缩容后要从集合移除,不能永远等待上报。 新扩容实例默认使用稳定版本,除非规则明确包含它。
七、隐私和观测
日志不直接记录手机号或邮箱,可记录受保护摘要、bucket 和 ruleId。 监控命中数、实际比例、版本收敛、规则冲突和主体缺失比例。 目标 5% 且有 100 万主体时约命中 5 万,明显偏差应检查哈希和口径。 跨语言客户端需固定编码、无符号取模规则和测试向量。
八、常见误区与追问
- 误区:每次随机数小于 5% 就是稳定灰度。 同一主体会来回跳变。
- 误区:写用户规则就能让实例配置按用户生效。 读取粒度必须匹配。
- 误区:哈希比例必然精确。 它只在足够样本下近似。
- 误区:多条命中时随便选一条。 必须有优先级和冲突检查。
- 追问:扩量如何保留原灰度用户? 固定盐与算法,只提高连续桶阈值。
- 追问:跨语言不一致怎么办? 固定编码、算法和公开测试向量。
- 追问:如何快速排除故障租户? 用更高优先级排除规则并设有效期。
九、加强记忆
- 命中粒度与配置读取粒度一致。
- 选稳定主体,用固定盐确定性分桶。
- 多类规则有明确优先级。
- 规则版本化,决策可解释、可复现。
- 用命中比例、版本收敛和业务指标验证结果。