OpenFeature 与特性开关全生命周期治理

特性开关允许不重新部署代码就改变功能行为,可用于灰度、A/B 测试、紧急降级、权限控制和渐进式发布。OpenFeature 提供厂商中立的标准 API 和 SDK,使应用与具体开关平台解耦。但如果缺少治理,开关会演变为永久分支、权限后门和不可预测的生产配置。

一、OpenFeature 的角色

OpenFeature 定义统一的 Client、Provider、Evaluation Context、Hooks 和事件模型。Provider 对接具体的特性开关系统,应用代码只依赖标准 API。

业务代码 → OpenFeature SDK → Provider → Flag 管理系统
                │
              Hooks
        日志 / 指标 / Trace / 校验

OpenFeature 本身不是完整管理后台,不负责替你保存所有开关和审批。生产还需要 Provider、控制面、权限、审计和数据存储。

二、开关类型

Release Flag

用于隐藏未完成功能和渐进发布,完成后应删除。

Experiment Flag

用于 A/B 测试,需要实验分组、指标和统计结论,结束后固化结果并删除。

Ops Flag

用于熔断、降级、切换依赖和调整运行策略,可以长期存在,但必须有演练和权限控制。

Permission/Entitlement Flag

用于产品套餐或授权。它不能替代后端安全授权,客户端开关只能控制界面展示。

创建时必须声明类型、负责人、到期日和预期清理方式。

三、命名与元数据

建议使用稳定、可搜索的 Key,例如:

checkout.new-payment-flow
search.vector-retrieval
ops.disable-image-processing
entitlement.advanced-report

每个 Flag 至少记录:说明、业务负责人、技术负责人、创建时间、到期时间、环境、风险等级、默认值、紧急回退值、关联工单和删除条件。

禁止使用 flag1、newFeature 等模糊名称,也不要把密码、URL 和任意配置都塞进 Feature Flag。

四、默认值与故障策略

SDK 调用必须传入类型明确的默认值。Provider 不可用、网络超时、配置错误或类型不匹配时,应返回经过设计的安全默认值并记录原因。

boolean enabled = client.getBooleanValue(
    "checkout.new-payment-flow",
    false,
    evaluationContext
);

默认值不是随便写 false。安全降级、支付、权限和数据写入场景要评估 Fail-Open 还是 Fail-Closed。不同环境的默认策略也可能不同。

五、Evaluation Context 与隐私

上下文可包含用户、租户、地域、应用版本和设备信息,用于定向规则。只传递评估必要字段,避免把姓名、手机号、完整 Token 或敏感标签发送到开关服务。

上下文字段必须形成字典,固定数据类型与来源。用户 ID 用稳定匿名标识,保证百分比分桶一致。字段变化会造成同一用户被重新分组。

六、百分比灰度与一致分桶

百分比发布应使用稳定哈希,确保同一主体持续落入同一 Variant。先定义分桶主体:用户、租户、设备还是请求。不能今天按用户、明天按会话。

灰度流程:

内部用户 → 1% → 5% → 20% → 50% → 100%

每阶段设置最短观察时间、错误率、延迟、业务成功率和自动停止条件。高峰与低峰数据分布不同,不要在几分钟无错误后直接全量。

七、紧急降级

Ops Flag 可以关闭非核心功能、切换缓存、限制高成本查询或禁用故障依赖。每个降级开关必须定期演练,确认代码路径仍有效。

紧急开关要求:

  • 明确允许操作的人;
  • 快速但有审计;
  • 修改后自动通知;
  • 安全默认值;
  • 生效延迟可观测;
  • 有恢复条件;
  • 防止遗忘在降级状态。

开关平台不可用时,最关键的降级能力仍应有本地缓存或静态兜底。

八、Provider 与缓存

Provider 可能本地评估或远程评估。远程模式规则集中但依赖网络;本地模式延迟低且抗断网,但需要可靠配置分发。

评估:

  • 配置更新协议;
  • 本地缓存和最后已知值;
  • 启动时 Provider 未就绪;
  • 超时和重试;
  • 多语言一致性;
  • 离线与边缘环境;
  • 配置签名;
  • 大规模客户端推送。

禁止每个业务请求都同步访问远端控制面且没有超时。

九、Hooks 与可观测性

Hooks 可在评估前后执行校验、日志、指标和 Trace。记录 Flag Key、Variant、Reason、Provider 和错误,但避免写入完整敏感上下文。

推荐指标:

  • 评估次数与延迟;
  • 默认值回退次数;
  • Provider 错误;
  • 各 Variant 流量;
  • 配置版本;
  • 更新传播延迟;
  • 无人引用或长期未变化 Flag;
  • 到期未清理 Flag。

业务指标必须能按 Variant 对比,否则无法判断灰度结果。

十、审批与权限

生产 Flag 修改属于变更。按风险区分:

  • 低风险 Release Flag 可由团队审批;
  • 高风险支付、权限、数据写入需双人复核;
  • 紧急 Ops Flag 可先执行后补审计,但限定人员;
  • 实验分流需产品和数据负责人确认。

权限按项目、环境和 Flag 范围最小化。开发人员不应默认拥有生产全局开关权限。服务账号与个人账号分离。

十一、开关与安全授权边界

客户端 Flag 值可以被用户篡改,不能作为权限校验。涉及付费功能、数据访问和管理操作时,后端必须执行真实授权。

特性开关也不能替代 Secret 管理、动态配置中心或数据库迁移工具。使用范围越清晰,系统越可控。

十二、数据库和 API 演进

开关常跨越代码、数据库和 API,必须采用向后兼容的 Expand/Contract:

  1. 先增加兼容 Schema;
  2. 发布能同时处理新旧数据的代码;
  3. 开启小流量新路径;
  4. 完成数据回填;
  5. 全量并观察;
  6. 删除旧读写;
  7. 最后删除旧 Schema 和 Flag。

不能用 Flag 瞬间切换不兼容数据库结构。

十三、测试策略

至少测试:默认值、开/关、所有 Variant、Provider 故障、配置类型错误、上下文缺失、规则边界、缓存过期和恢复。

组合爆炸时按风险选取关键 Flag 组合,并限制同时影响同一代码路径的 Flag 数量。自动化测试可以使用 In-Memory Provider 或 Test Provider,不要依赖生产控制面。

十四、技术债清理

Release Flag 完成全量后应删除:

确认全量稳定 → 固化新路径 → 删除旧路径
→ 删除 SDK 调用 → 删除控制面 Flag → 更新文档

建立自动扫描:代码引用、创建日期、到期日期、负责人、最近评估和最后修改。无负责人、超期或永远固定值的 Flag 自动建工单。

长期保留的 Ops Flag 也要定期演练和复核默认值。

十五、多环境和 GitOps

开发、测试、预生产、生产应独立配置和权限。生产规则不能自动被开发环境覆盖。使用 GitOps 管理时,配置变更经过 PR、签名、策略校验和审计;紧急修改要回写 Git,避免漂移。

不能在仓库中保存敏感目标名单。大规模规则更新先做 Dry Run 或影响分析。

十六、灾难恢复

备份 Flag 定义、规则、环境、权限、审计、Provider 配置和 SDK 版本。恢复后验证控制面、分发、缓存、评估结果和审计。

应用要在控制面故障时继续使用最后已知配置或安全默认值。定期断开 Provider,观察核心业务是否可接受。

十七、常见故障

修改后部分实例不生效

检查 Provider 连接、缓存、配置版本、推送、时钟、SDK 版本和评估上下文。

百分比流量不稳定

检查分桶 Key 是否稳定、客户端实现是否一致、匿名用户标识和 Variant 权重。

Provider 故障导致延迟升高

检查是否远程同步评估、超时过长、重试风暴和本地缓存。

关闭 Flag 仍执行新逻辑

检查默认值、多个 Flag、缓存、代码路径和异步任务。用 Trace 标记实际 Variant。

Flag 无法删除

通过代码搜索、运行时评估数据和 Owner 确认引用,先删除代码依赖再删除控制面定义。

十八、生产检查清单

  • [ ] 每个 Flag 有类型、Owner 和到期日;
  • [ ] 默认值经过 Fail-Open/Fail-Closed 评审;
  • [ ] Evaluation Context 不包含无关敏感信息;
  • [ ] 百分比分桶主体稳定;
  • [ ] 灰度阶段有指标和停止条件;
  • [ ] Provider 故障有缓存与兜底;
  • [ ] 生产修改有最小权限和审计;
  • [ ] 后端授权不依赖客户端 Flag;
  • [ ] 数据库变更使用 Expand/Contract;
  • [ ] 所有 Variant 有自动化测试;
  • [ ] 超期 Flag 自动发现和清理;
  • [ ] 已演练控制面不可用。

参考资料

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-11-04 16:12:51

results matching ""

    No results matching ""