使用split_clients在网关层做A/B测试需选稳定可复现的用户标识变量,如$cookie_uid(精度最高)、$binary_remote_addr(无登录场景)或$arg_uid(需业务配合),通过哈希而非随机实现同一用户始终分入同组,并配合map预处理、URL强制覆盖及日志追踪确保稳定性与可观测性。

直接用 split_clients 在网关层做基于用户特性的 A/B 测试,核心是选对“用户标识变量”,并确保它稳定、可复现、跨请求一致。它不是随机打散,而是靠哈希锁定——同一个用户,无论刷多少次,都进同一组。
选准分流依据:哪些变量真正代表“用户”
IP 地址最易得,但不精准:内网用户共用一个出口 IP,会全进同一组;移动网络频繁换 IP,又可能被反复分到不同版本。更可靠的用户标识有:
- $cookie_uid 或 $cookie_ab_group:后端登录后写入的唯一用户 ID,跨设备、跨会话稳定,精度最高
- $binary_remote_addr:比 $remote_addr 更紧凑、哈希一致性更强的二进制 IP 表示,适合无登录场景下的基础分流
-
$arg_uid(需业务配合):URL 显式携带可信 UID,如
/dashboard?uid=abc123,前提是前端或跳转链路能可靠传入 -
拼接组合键:如
"$cookie_uid|$http_user_agent",在 cookie 存在时增强区分度;但注意 UA 在隐私模式或 WebView 下可能变化,慎用
配置写法:权重分配与变量传递
分流逻辑必须定义在 http{ } 块顶层,不能放在 server 或 location 内。典型结构如下:
http {
split_clients "$cookie_uid" $ab_version {
5% "v2";
* "v1";
}
upstream backend_v1 { server 10.0.1.10:8080; }
upstream backend_v2 { server 10.0.1.11:8080; }
server {
location / {
proxy_pass http://backend_$ab_version;
proxy_set_header X-AB-Version $ab_version;
}
}
}
说明:
- 空 cookie 会被哈希为空字符串,导致大量流量集中到 * 分支——务必配合 map 预处理或 fallback 逻辑
- 百分比只支持整数(如
5%合法,5.5%不合法),内部按万分比映射 -
$ab_version是纯字符串变量,可直接拼进proxy_pass、add_header或日志中用于追踪
补足稳定性:应对 cookie 缺失与强制覆盖
真实场景中,首次访问用户没有 $cookie_uid,需要兜底策略;同时测试人员常需手动切版本。推荐组合方案:
先用 map 检查 cookie 是否有效,再 fallback 到 IP 或生成临时标记:
map $cookie_uid $ab_group {
"" "ip_based";
~. "cookie_based";
}
split_clients "$cookie_uid|$binary_remote_addr" $version {
3% "v2";
* "v1";
}
再加一层 URL 参数优先级覆盖:
- 用
map $arg_ab_force $forced_version { default ""; "v2" "v2"; "v1" "v1"; } - 在 proxy_pass 前判断:
if ($forced_version) { set $version $forced_version; }
验证与可观测性要点
分流是否生效,不能只看配置 reload 成功。关键验证动作:
- 用不同 UID 的 curl 请求,检查响应头
X-AB-Version是否稳定且符合比例(如 100 次请求中约 5 次返回 v2) - 在 access_log 中加入
$ab_version和$cookie_uid字段,便于按用户维度聚合分析 - 避免用
$args或$http_referer等易变字段作输入,否则哈希漂移会导致同用户分组跳变,AB 数据失效

















