feature flag / 灰度发布:decide 出一个 variant
「先为 10% 用户开启新版结算」「内测账号直接开启,美区暂不开启」—— feature flag 的求值,同样是这个函数:
who (用户 + 属性) → 看到哪个 variant。与 HTTP、pricing 两个实例一样,它将 policy 略作推广:输出不是 permit/deny,
而是一个 variant (ON/OFF,或 A/B/C);而 targeting 规则从上到下、第一条命中即生效 ——
这正是 05-decide 的 first-applicable。
who
用户 + 属性
id / country / plan / beta → targeting
what
这个 flag
被开关的功能,如 new-checkout
action
evaluate
页面渲染时求值「该给他看哪版」
when
发布阶段
灰度 % 随时间逐步放量
flag 求值:targeting 规则 + 个体定向
● 用户 (who) —— 选预设再改属性
country
plan
beta 内测
🚩 flag 配置 (这就是 policy)
targeting 规则 (从上到下,第一条命中即生效;可单独停用)
30%
求值轨迹 (亮 = 走到这步;高亮 = 决定 variant 的那步)
first-applicable,与防火墙规则链、05-decide 的算法完全一致。
百分比灰度:确定性分桶,稳定且单调
未被规则命中的用户,进入百分比灰度。关键在于:不能每次随机取值 (否则同一用户时而看到新版、时而看到旧版)。
做法是将 hash(flagKey + ":" + userId) 映射到一个固定的桶 0–99,桶号 < 放量% 即开启。
下面 100 个用户按桶排列,拖动放量滑块即可看到哪些被点亮 (当前用户以黑框标示):
30 / 100 用户开启
放量 30%
稳定 (sticky):同一
userId 的桶号始终不变 —— 用户体验一致,不会出现闪烁。
单调 (monotonic):放量从 30% 提升至 50%,只会新增用户进入,已开启的绝不会被关闭 —— 放量始终安全、可回滚。
每个 flag 独立:hash 中包含
flagKey,因此一个用户在 flag A 进入了灰度,在 flag B 未必如此 —— 避免「同一批人覆盖所有实验」。
这实际上为 policy 增加了一种特殊的 who 分组:伪随机,但确定、可复现。
feature flag 概念 → policy 概念
| flag 里的说法 | policy 里的概念 (第 01–05 页) |
|---|---|
| targeting 规则的条件 | 规则条件 when(req) (看 who 的属性 = ABAC) |
| 规则从上到下、第一条命中 | first-applicable「顺序即优先级」 |
| 个体定向 (allowlist) | 显式 allow 覆盖 (像 RBAC 的 UserAllow) |
| 百分比灰度 (hash 分桶) | 确定性的 who 分组:伪随机但稳定可复现 |
| default / fallthrough variant | 默认决策 (没规则命中时的最终取值) |
| flag 总开关 (kill switch) | 全局 disable / 一次关闭 |
| variant (ON/OFF 或 A/B/C 多分支) | decision 是枚举值,不是布尔 (像 pricing 是个价) |
相关链接
- 回看:决策与组合算法 (first-applicable·default·kill switch 都在这)@vega/playgroundflag 的求值顺序就是 first-applicable + 默认决策。
- LaunchDarkly · Targeting rules & rolloutsdocs.launchdarkly.com个体定向 / 规则 / 百分比灰度 / 默认 variant 的工业实现。
- Unleash · Activation strategiesdocs.getunleash.io开源 feature flag 的策略模型 (gradualRollout / userWithId 等)。