系统设计 / 访问控制 · 从 RBAC 查表到 policy 判定函数 / feature flag / 灰度发布:decide 出一个 variant 待审核 21 / 23
实例 · feature flag / 灰度

feature flag / 灰度发布:decide 出一个 variant

「先为 10% 用户开启新版结算」「内测账号直接开启,美区暂不开启」——feature flag 的求值,同样是这个函数:who(用户 + 属性)决定看到哪个 variant。与 HTTP会员价与优惠券 两个实例一样,它将 policy 略作推广:输出不是 permit/deny,而是一个 variant(ON/OFF,或 A/B/C);而 targeting 规则从上到下、第一条命中即生效——这正是 first-applicable

图 0-1 · feature flag 场景里的四个轴各自对应什么。

注 · flag 的求值顺序(LaunchDarkly 等均采用此模型):先看 flag 总开关,关闭就直接 OFF(kill switch);再看个体定向(allowlist,QA / 内部账号直接开);然后 targeting 规则从上到下,第一条命中就用它的 variant;都没命中则进百分比灰度(按 hash 分桶,命中就 ON);最后落到 default variant。每一步都对应 policy 里的一个概念。

1 · flag 求值:targeting 规则与个体定向

顺序即优先级。Ben(US · pro)身上,规则「美区 → OFF」排在「Pro → ON」前面,第一条命中即胜出;停用前者,后者接管。Cody(US · 内测)则因「内测 → ON」位于最前,即便在美区也是 ON。调换两条规则的顺序,结论可能反转——这就是 first-applicable,与防火墙规则链同一机制。

图 1-1 · 一次 flag 求值走过的完整轨迹。可切换用户与属性、开关总开关与个体名单、停用某条 targeting 规则,观察哪一步决定了 variant。

2 · 百分比灰度的确定性分桶

未被规则命中的用户进入百分比灰度。关键在于不能每次随机取值,否则同一用户时而看到新版、时而看到旧版。做法是将 hash(flagKey + ":" + userId) 映射到一个固定的桶 0–99,桶号小于放量百分比即开启。

图 2-1 · 100 个桶按放量百分比点亮的情况,当前用户所在的桶以黑框标示。可拖动放量滑块,观察点亮范围只增不减。

建议 · 这样分桶在工程上可靠有三个理由。稳定(sticky):同一 userId 的桶号始终不变,用户体验一致,不会闪烁。单调(monotonic):放量从 30% 提到 50%,只会新增用户进入,已开启的绝不会被关闭,放量始终安全、可回滚。每个 flag 独立:hash 中包含 flagKey,因此一个用户在 flag A 进入了灰度,在 flag B 未必如此,避免「同一批人覆盖所有实验」。这实际上为 policy 增加了一种特殊的 who 分组:伪随机,但确定、可复现。

3 · feature flag 概念映回 policy 概念

表 3-1 · flag 术语与前五页 policy 概念的逐条对应。A/B 实验是把灰度桶分流到多个 variant 再测指标,本质仍是「who → 哪个分支」。
flag 里的说法 policy 里的概念
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 是枚举值,不是布尔(像定价是个价)

4 · 参考文献

  1. LaunchDarkly. Target with flags. targeting 规则、个体定向与默认 variant 的工业实现。launchdarkly.com
  2. LaunchDarkly. Percentage rollouts. 按 hash 分桶的百分比灰度,本页第 2 节的工业对照。launchdarkly.com
  3. Unleash. Activation strategies. 开源 feature flag 的策略模型(Gradual rollout / Standard / Custom strategies)。docs.getunleash.io