Feature Flags和幻想发布
Feature Flag (FF)是一种受控条件,它启用/关闭系统行为而无需发布代码。标志允许:安全地推出菲奇,针对用户/市场/tenant组,快速禁用有问题的组件,进行实验,并在随机时配置参数。
主要目标:- 在发布时降低blast radius。
- 将部署和激活分开。
- 通过审核、SLO和"一键回滚"提供透明的变更管理。
1)国旗的类型以及何时使用
Release flags-分阶段包含新仙女(dark → canary → ramp-up → 100%)。
Ops/kill-switch-即时断开依赖关系(提供程序、子系统、重型计算)。
实验(A/B, multi-variant)-将流量划分为变体(权重、紧缩)。
Permission/Entitlement-按角色/计划/司法管辖区访问钓鱼。
Remote Config-标志/config中的行为参数(阈值、定时、公式)。
Migration flags-电路/数据路径切换(移至新索引/DB/端口)。
反模式:相同的"关于一切"标志-粉碎在前线,复卷轴和参数上。
2)标志数据模型(最小值)
yaml flag:
key: "catalog. new_ranker"
type: "release" # release ops kill experiment permission config migration description: "New Directory Ranking"
owner: "search-team@company"
created_at: "2025-10-01T10:00:00Z"
ttl: "2026-01-31" # delete deadline after 100% enable rules:
- when:
tenant_id: ["brand_eu","brand_latam"]
region: ["EE","BR"]
user_pct: 10 # progressive percentage then: "on"
- when:
kyc_tier: ["unverified"]
then: "off"
variants: # for experiments
- name: "control"; weight: 50
- name: "v1"; weight: 30
- name: "v2"; weight: 20 payload:
v1:
boost_freshness: 0. 3 boost_jackpot: 0. 2 v2:
boost_freshness: 0. 2 boost_jackpot: 0. 4 prerequisites: # dependent flags/schema versions
- key: "catalog. index_v2_ready"
must_be: "on"
audit:
require_ticket: true change_window: "09:00-19:00 Europe/Kyiv"
safeguards:
max_rollout_pct: 50 # stop threshold auto_rollback_on:
p95_ms: ">200"
error_rate: ">2%"
3)评估和定位(评估)
Ключи таргетинга: `tenant_id, region/licence, currency, channel, locale, role, plan, device, user_id, cohort, kyc_tier, experiment_bucket`.
评分顺序:先前的→ deny规则→ allow规则→默认。
Sticky bucketing:对于实验,哈希稳定标识符(例如"hash(user_id,flag_key)")-让用户始终收到一个选项。
ts result = evaluate(flag, context) // pure function if (!prereqs_ok(result)) return OFF if (deny_match(result, ctx)) return OFF if (allow_match(result, ctx)) return resolve_variant_or_on(result, ctx)
return flag. default
4) FF分配和体系结构
变体:- 服务器侧SDK(建议):后端的真实来源和缓存;逻辑统一。
- Edge/CDN评估:在外围快速定位(没有PII/秘密)。
- Client-side SDK:当需要UI个性化时,但是-只有极少的上下文且没有敏感规则。
- Config-as-Code:将旗帜存储在存储库中,CI验证,通过CD滚动。
- Startup bootstrap+streaming updates (SSE/gRPC)+fallback to last snapshot。
- Flags的SLA "freshness":p95 ≤ 5。
5)发布策略
5.1 Dark Launch
启用了Ficha,但用户看不见;收集指标和错误。
5.2 Canary
在一个司法管辖区/tenant中包含1-5%的流量;监视p95/p99,错误,转换。
Stop conditions-根据度量标准自动触发器的阈值触发器。
5.3 Progressive Rollout
10%→ 25%→ 50%→ 100%的手动/自动验证时间表。
5.4 Shadow / Mirroring
将查询重复到新路径(没有可见效果),并比较结果/潜伏期。
5.5 Blue/Green + FF
我们展开两个版本。标志通过流量滚动并按段切换约束。
6)依赖性和跨服务一致性
使用prerequisites和"健康标志"准备就绪:索引构建,迁移完成。
通过事件进行协调:"FlagChanged(flag_key,scope,new_state)"。
1.启用read路径→ 2)检查度量→ 3)启用write/side-effects。
- 服务合同:违约必须安全(失败安全)。
7)可观察性和SLO
每个标志/变体/段的度量:- `flag_eval_p95_ms`, `errors_rate`, `config_freshness_ms`.
- 业务指标:'ctr','conversion','ARPU','retention',guardrails(例如RG事件)。
- 自动变频器的自动SLO阈值。
Logi/Tracing:添加"flag_key"、"variant"、"decision_source" (服务器/edge/client)、"context_hash"。
Dashbords:带有阈值的"楼梯"滚动,按段排列错误。
8)安全和合规性
上下文中的PII最小化。
RLS/ACL:谁可以更改哪些标志(跨域/市场)。
更改时钟窗口(change windows)和敏感标志的"双重确认"。
不变审计:何人/何时/何时/为什么(ticket/incident link)。
司法管辖区:旗帜不应绕过监管禁令(例如,在被禁止的国家包括游戏)。
9)管理"长寿"旗帜
每个标志都有TTL/删除日期。
100%启用后-创建一个任务以删除代码分支,否则将增加标记-债务。
将标志标记为"migration"/"one-time",将它们与永久的"permission/config"分开。
10)合同API/SDK示例
Evaluation API (server-side)
http
POST /v1/flags/evaluate
Headers: X-Tenant: brand_eu
Body: { "keys":["catalog. new_ranker","rgs. killswitch"], "context": { "user_id":"u42", "region":"EE" } }
→ 200
{
"catalog. new_ranker": { "on": true, "variant":"v1", "as_of":"2025-10-31T12:10:02Z" },
"rgs. killswitch": { "on": false, "variant":null, "as_of":"2025-10-31T12:10:02Z" }
}
Client SDK (кэш, fallback)
ts const ff = await sdk. getSnapshot() // bootstrap const on = ff. isOn("catalog. new_ranker", ctx)
const payload = ff. payload("catalog. new_ranker", "v1")
11)与其他路径的交互
比例限制/配额:在事件发生时,旗帜可能会降低RPS/包括旋转。
电路断路器/断路器:kill-switchi禁用重轨并包括降级。
目录/个性化:标志更改权重/排名规则(通过Remote Config)。
DB迁移:标志分阶段将读/写转换为新模式(read-replica → dual-write → write-primary)。
12)花花公子(runbooks)
1.包括后事件25%
Autocatof为所有/细分市场工作了→个OFF标志,在呼叫中滴答作响,收集雕像,RCA。
通过迁移标志暂时启用降级/旧分支。
2.按目录分列的p95增长
阈值'p95_ms> 200'是自动触发器;用'flag_key=catalog捕捉日志。new_ranker`.
启用简化的排名信号(payload config)。
3.管辖权不匹配
Permission标志错误地在"NL"-OFF+事实审核中打开了游戏,并添加了"region deny"守卫规则。
4.A/B中的方差
停止实验,执行CUPED/stratified分析,重新调整权重。
13)测试
单位:确定性地评估规则/优先事项/预告。
合同: 标志图(JSON/YAML),验证器,CI验证,merge之前.
基于物业:"deny> allow","most specific wins",稳定击球。
Replay:在新配置上播放实际上下文。
E2E:金丝雀脚本(step-up/step-down)、自动静态检查和审计事件。
混乱:流媒体破裂,过时的狙击,大规模的旗帜更新。
14)典型错误
客户端标志中的秘密逻辑(泄漏/替换)。
缺少TTL →代码中的旗帜"墓地"。
没有分割的"通用"标志→无法本地化问题。
没有guardrails/autocatophs-手动事件。
标志之间不兼容的依赖关系→循环/旋转。
在没有缓存的情况下评估每个请求中的标志→潜伏期激增。
没有审计/更改窗口-合并风险。
15)售前支票清单
- 国旗的创建具有类型,所有者,描述,TTL和字幕要求。
- 目标规则定义;"deny"指不需要的区域/角色。
- 确定性坚韧不拔;选择的标识符是一致的。
- 预告片和卫生标志已准备就绪;默认是安全的。
- Dashbords和Alerta在p95/p99,error_rate,商业护栏上。
- Autocatoff定制;停止阈值滚动和回滚条件。
- 金丝雀计划:利息/阶段/变更窗口/责任。
- Configs在CI中得到验证;狙击手分布在集群/地区。
- 支持/产品文档;事件的花花公子。
- 100%后删除代码分支和标志本身的计划。
16)"迁移"标志示例(DB/索引)
yaml flag:
key: "search. use_index_v2"
type: "migration"
description: "Switching reads to index v2"
prerequisites:
- key: "search. index_v2_built"
must_be: "on"
rules:
- when: { tenant_id: ["brand_eu"], user_pct: 5 } then: "on"
- when: { tenant_id: ["brand_eu"], user_pct: 25 } then: "on"
safeguards:
auto_rollback_on:
search_p95_ms: ">180"
error_rate: ">1%"
ttl: "2026-02-01"
结论
Feature Flags不仅是"打开/关闭",而且是变更风险管理的学科。清晰的标志类型,确定性的目标,带有guardrails,autocatoff,审核和删除计划的渐进式布局使发布变得可预测,并且事件简短且可控制。将标志作为第一类公民嵌入体系结构-您可以更频繁,更安全,更有意义地传递价值。