nginx 实现 a/b 测试需依赖 split_clients 模块保障用户分流稳定性与比例可控性,配合 return 302 完成跳转;不可仅靠 302 重定向随机分发。

在 A/B 测试中,Nginx 的 302 重定向本身不直接支持“随机分发”,因为它只是响应级跳转,不具备内置哈希或概率分流能力。真正实现用户随机/稳定分流的核心是 split_clients 模块,再配合 return 302 完成条件跳转。关键不是让每次请求“随机跳”,而是让同一用户始终被分到同一组(稳定性),同时整体流量按比例分配(可控性)。
用 split_clients 预定义分流变量
这是最推荐、最稳定的方式。它基于客户端标识(如 IP、Cookie)做哈希计算,确保用户粘性,避免同一个人在 A/B 间来回跳转:
- 在
http块中定义分流逻辑,例如 50% 用户进 A 版,50% 进 B 版:
split_clients "${remote_addr}AAA" $ab_group {
50% .a;
50% .b;
}
}
-
${remote_addr}AAA是哈希输入,加固定后缀(如 AAA)提升散列均匀性;$ab_group是生成的变量,值为.a或.b - 若需更高精度(比如 10% 灰度),可写
10%.a; 90%.b;
在 server 或 location 中按变量执行 302 跳转
有了稳定的分组变量,就可以用 return 302 把对应用户导向不同目标地址,同时保留原始请求路径和参数:
- 示例:对所有请求,根据分组跳转到不同子域
listen 80;
server_name example.com;
if ($ab_group = ".a") {
return 302 https://a.example.com$request_uri;
}
if ($ab_group = ".b") {
return 302 https://b.example.com$request_uri;
}
}
-
$request_uri确保/product?id=123&utm_source=test完整透传,测试数据不丢失 - 不用
rewrite,避免 flag 冲突;不用error_page,防止内部重写误判
替代方案:用 Cookie 或 Header 做轻量级分流
如果无法使用 split_clients(如某些精简版 Nginx),可用 if + return 302 结合客户端特征简单分流,但注意稳定性较弱:
- 按 Cookie 分流(适合已埋点的用户):
if ($cookie_ab_test = "A") { return 302 https://a.example.com$request_uri; } - 按请求头(如内网测试):
if ($http_x_ab_version = "B") { return 302 https://b.example.com$request_uri; } - 按 IP 段(仅限灰度环境):
if ($remote_addr ~ ^(192\.168|10\.) ) { return 302 https://beta.example.com$request_uri; }
必须验证的三个要点
配置生效前,务必逐项确认:
- 用
curl -I http://example.com/查看响应头:必须是HTTP/1.1 302 Found,且Location值正确,不含Cache-Control: public - 用隐身窗口或清空 Cookie/缓存反复访问同一 URL,检查是否始终跳往同一版本(验证用户粘性)
- 检查非测试用户(如未带指定 Cookie 或不在 IP 段)是否仍返回 200,不被误跳











