split_clients 必须置于 http 块顶层,语法为 split_clients "input" $var { percent% "val"; "default"; },输入需加引号,百分比总和≤100%,仅能出现一次且在末尾,变量名仅限字母、数字、下划线。

split_clients 必须放在 http { ... } 块内,不能写在 server 或 location 中,它是全局生效的变量定义指令,用于生成一个稳定、可复用的分流标识变量。
核心结构要求:
- 位置固定:仅允许出现在
http上下文 - 语法严格:输入字符串需加引号,百分比总和 ≤100%,兜底项必须用
* - 变量命名规范:目标变量名只能含字母、数字、下划线,不能含短横线或特殊符号
正确的配置位置与基本格式
http {
# ✅ 正确:split_clients 在 http 块顶层
split_clients "$remote_addr" $ab_group {
5% "v2";
* "v1";
}
upstream backend_v1 {
server 10.0.1.10:8080;
}
upstream backend_v2 {
server 10.0.1.20:8080;
}
server {
location / {
proxy_pass https://backend_$ab_group;
proxy_set_header Host $host;
}
}
}注意:
$ab_group是由split_clients计算出的值,后续可在proxy_pass、upstream名称、map或响应头中直接引用。
输入字符串怎么构造更可靠?
单一 $remote_addr 在有 CDN 或反向代理时会失效(所有请求显示为同一个 IP)。推荐以下组合方式:
- 用真实客户端 IP(需前端透传):
"$http_x_forwarded_for" - 用登录态 ID(最精准):
"$cookie_uid"或"$arg_uid" - 混合防碰撞:
"$cookie_uid-$remote_addr"或"$http_user_agent-$remote_addr"
split_clients "$cookie_uid" $exp_group {
10% "test";
* "control";
}若
$cookie_uid为空,Nginx 会哈希空字符串,结果恒定但不区分用户。建议配合map提供兜底:
map $cookie_uid $uid_for_split {
"" $remote_addr;
default $cookie_uid;
}
split_clients "$uid_for_split" $exp_group {
10% "test";
* "control";
}百分比写法注意事项
- 支持小数:
0.5%、2.33%都合法 - 总和不必强制 100%:未覆盖部分自动归入
*分支 -
*只能出现一次,且必须是最后一项 - 不要写成
100%+*,会报错
# ✅ 合理:95% 明确指定,5% 自动兜底
split_clients "$remote_addr" $ver {
95% "prod";
* "canary";
}
# ❌ 错误:两个 *,或 * 不在末尾
split_clients "$remote_addr" $ver {
* "canary";
95% "prod"; # 语法错误
}常见错误与修复
-
变量名含短横线 →
"$backend-version"报错 → 改为"$backend_version" -
输入变量没加引号 →
split_clients $remote_addr $v { ... }报错 → 必须写成"$remote_addr" -
放在 location 内 → Nginx 启动失败,提示
unknown directive "split_clients" -
用
$ssl_protocol等 SSL 相关变量 → 值为空或不可用,因split_clients执行早于 SSL 握手完成
不复杂但容易忽略


















