Skip to Content
产品功能远程配置与 Feature Flags

远程配置与 Feature Flags

远程配置(Remote Config)/ 功能开关(Feature Flag)让你不发版就能改变线上行为:在 Console 定义 flag 与定向规则,端上 SDK 周期拉取并本地缓存,业务代码用 getBoolean("new_ui", false) 这类 永不抛异常、永不返回空的 API 取值。最典型的用法是 kill switch——新功能出问题时在 Console 把开关关掉,等客户端下一次刷新即可止血,无需紧急发版。

服务端实现在 services/config (flag 定义、targeting 求值、GET /v1/config 下发)。PRD: docs/02-product/25-remote-config.md

核心概念

Flag 类型

类型取值典型用途
booleanon / off功能开关、kill switch
string任意字符串文案、主题名、API 版本号
number数值阈值、超时、列表长度
json对象或数组复杂结构化配置(如页面布局)

开关(enabled)语义

  • boolean flag:未命中任何规则时,取值 = 顶部开关状态(开 = true,关 = false)。
  • string / number / json flag:开启时未命中规则下发 default_value(服务端默认值); 关闭即不下发——客户端取到代码里的 default,这就是类型化 flag 的 kill switch 行为。

Targeting 规则

每个 flag 可挂多条规则,按优先级(position)从上到下首个命中胜出

  • 匹配属性:platform(如 ios / android / web)或 app_version(如 2.3.0),等值匹配。
  • 命中返回值:boolean flag 返回 on / off;类型化 flag 返回一个符合声明类型的值。
  • 无规则命中 → 落到上面的 enabled / 默认值语义。

按百分比灰度放量(一致性 hash 分桶)、按 user attribute / region 定向、复合 AND / OR 规则为 规划中能力(版本级的百分比灰度已可用,见 版本与灰度发布)。

取值优先级:远程 > 缓存 > default(永不返回空)

SDK 的每次 getXxx(key, default) 按以下顺序回退,绝不返回 null / 绝不抛异常 / 绝不阻塞启动

  1. 本次进程内已成功拉取并通过类型校验的最新远程值
  2. 上次成功拉取的持久化缓存(跨启动存活);
  3. 调用方传入的 default(最后兜底)。

配套行为:拉取失败保留旧缓存(不回退 default,避免服务端抖动引发全网行为闪烁); 远程值类型与取值 API 不匹配(如远程下发字符串但代码取 boolean)时跳过该值回退Argus.init() 与首次取值不等待网络——冷启动有缓存用缓存、无缓存用 default,远程值后台 拉取成功后于下次取值生效。

生效时延(重要预期管理)

Console 上的修改立即写入服务端(控制平面实时),但已在运行的客户端要到 下一次后台刷新(默认 30 分钟,可配)或下次冷启动才拿到新值。紧急止血场景请把轮询间隔调短, 或等待实时推送(SSE,规划中)上线。

接入

平台矩阵

远程配置取值在 5 个端上 SDK 全部可用5 个后端 SDK(Go / Node / Python / Java / Rust) 均未实装 Remote Config 拉取(目标 API 见 后端 SDK 对照表 §6 ), 当前请以端上消费为主。

平台开启方式取值 API 前缀快速开始
WebArgus.init({ ..., remoteConfig: true })Argus.config.getXxx/quickstart/web/
iOSArgusConfig.remoteConfig = trueArgus.configGetXxx/quickstart/ios/
AndroidArgusConfig.Builder(dsn).remoteConfig(true)Argus.configGetXxx/quickstart/android/
FlutterArgusConfig(..., remoteConfig: true)Argus.configGetXxx/quickstart/flutter/
React NativeArgus.init({ ..., remoteConfig: true })Argus.config.getXxx/quickstart/react-native/

开启后 SDK 启动拉取一次 GET /v1/config 并按默认 30 分钟间隔后台轮询(间隔可在 init 配置, 如 iOS configPollInterval / Android configPollIntervalSeconds),结果持久化缓存。 拉取时携带 platform / app_version 等上下文,服务端按 targeting 规则求值后下发键值快照。

最小接入片段

Argus.init({ dsn: "argus://...", remoteConfig: true }); const newUI = Argus.config.getBoolean("new_ui_enabled", false); const theme = Argus.config.getString("theme", "light"); const layout = Argus.config.getJSON("checkout_layout", {});

永远给 getXxx 传一个业务上安全的 default——它是断网、首启无缓存、类型不匹配时的最终兜底。 上报与拉取的鉴权凭证见 DSN 与 HMAC

Console 使用

进入 Console 左侧导航 Feature Flags 页(先在左上角选择项目):

  1. 新建 Flag:填 key(如 new_ui)、描述(可选)、类型(boolean / string / number / json); 非 boolean 类型需填默认值(json 需为对象或数组)。key 重复返回 409 提示换名。
  2. 开 / 关:列表中直接勾选切换 enabled;对类型化 flag 而言”关闭 = 不下发 = kill switch”。
  3. 编辑规则:展开某 flag 的规则面板——选择属性(platform / app_version)、填目标值、 设定命中时返回(boolean 选 on / off,类型化 flag 填符合类型的返回值),规则按优先级从上到下 首个命中胜出;可逐条删除。
  4. 删除 Flag:不可撤销,删除前二次确认。

列表字段:Key、状态(已开启 / 已关闭)、类型 / 默认值、描述、规则数、操作。

SDK API 速查

取值Web / React NativeiOSAndroidFlutter
BooleanArgus.config.getBoolean(key, def)Argus.configGetBoolean(key, def)Argus.configGetBoolean(key, def)Argus.configGetBoolean(key, def)
StringArgus.config.getString(key, def)Argus.configGetString(key, def)Argus.configGetString(key, def)Argus.configGetString(key, def)
JSONArgus.config.getJSON(key, def)Argus.configGetJSON(key, def)Argus.configGetJSON(key, def)Argus.configGetJSON(key, def)
实验变体Argus.config.getVariant(key, def)Argus.configGetVariant(key, def)Argus.configGetVariant(key, def)Argus.configGetVariant(key, def)

getVariant 返回该用户在 A/B 实验中被分到的变体(随配置包一起下发),详见 A/B 实验

MCP 工具

接入 Argus MCP Server 后可让 AI 查线上配置现状 (源码:config_get.ts):

工具用途关键参数
config.get项目当前生效的远程配置:求值后的 flag 值、实验分配、生效中的灰度版本project_id,可选 platform / app_version(模拟某客户端上下文求值;缺省为项目默认)

典型提问:“new_ui_enabled 在 iOS 2.3.0 上现在下发什么值?”、“当前有哪些 flag 是关着的?“

配额与计费

  • 配置拉取按实际到达服务端的请求计量(约 1000 次配置请求 = 1 个计费事件,以计费页为准); SDK 本地缓存命中不产生请求、不计费——轮询间隔越长消耗越低。
  • 详见 套餐、配额与计费

FAQ

我在 Console 改了 flag,客户端为什么没变化? 已运行的客户端要到下次后台刷新(默认 30 分钟)或下次冷启动才拿到新值——这是轮询模型的预期行为。 依次排查:① init 是否开了 remoteConfig;② flag 是否 enabled、规则是否命中该 platform / app_version;③ 取值 API 类型是否与 flag 声明类型一致(不一致会回退 default)。可用 MCP config.get 模拟该客户端上下文核对服务端实际下发值。

断网 / 服务端不可用时取值是什么? 有缓存取缓存(上次成功拉取的值),从未拉取成功过则取 default。后台刷新失败不会把已生效的值 回退成 default。

类型化 flag 关闭后客户端取到什么? 关闭即不下发该 key,客户端落到代码 default——所以 default 应当是”功能关闭”的安全值。

支持按百分比放量吗? flag 级的百分比 rollout(一致性 hash 分桶)为规划中;当前如需按百分比灰度,可用 版本灰度发布(已支持百分比 + 定向白名单),或用 A/B 实验的权重分流。

改动能实时推送到端上吗? v1.5 为纯轮询拉取,无服务端推送;SSE / WebSocket 实时推送为规划中。对时效敏感的开关请调短 轮询间隔(代价是请求量与配额消耗上升)。