灰度发布中Nginx用return 302实现临时跳转,推荐按Cookie、请求头或IP判断用户并精准分流,务必保留$request_uri、写全目标协议,非灰度流量保持200响应。

灰度发布中用 Nginx 把特定用户群临时跳转到新版,核心就是靠 302 重定向 + 条件识别——它不改 SEO 权重、不被浏览器长期缓存,出问题随时关掉配置就能回退。
必须用 return 302,别写 rewrite 或 permanent
直接在 server 或 location 块里写:
return 302 https://new.example.com$request_uri;
这样语义清晰、性能好、无正则开销。rewrite redirect 虽然也发 302,但容易因匹配逻辑或 flag 混用引发循环跳转或意外行为。
按用户特征精准分流的三种常用方式
-
按 Cookie 区分:比如灰度用户带
version=beta,配置:
if ($cookie_version = "beta") { return 302 https://new.example.com$request_uri; } -
按请求头判断:测试人员访问时加
X-Env: beta,配置:
if ($http_x_env = "beta") { return 302 https://new.example.com$request_uri; } -
按 IP 段控制:内网测试常用,例如只对 192.168.x.x 用户生效:
if ($remote_addr ~ ^(192\.168|10\.)) { return 302 https://new.example.com$request_uri; }
关键细节不能漏
-
$request_uri 要保留:它包含原始路径和全部查询参数(如
/product?id=123&utm_source=gray),确保新版能正确处理上下文 -
目标地址写全协议:必须是
https://...或http://...,避免相对路径导致协议错乱或跨域失败 - 非灰度用户不受影响:条件跳转外的请求应正常走原逻辑,状态码仍为 200;别让 if 块覆盖整个流量
-
上线前务必验证:用
curl -I看响应头是否为HTTP/1.1 302 Found且含正确Location,再用隐身窗口测试真实跳转效果
更健壮的写法:用 map 替代 if(推荐用于复杂场景)
if 在 location 外使用有执行顺序风险,可改用 map 预定义变量提升稳定性:
map $http_cookie $is_gray {
~*version=beta "1";
default "0";
}
server { ...
if ($is_gray = "1") { return 302 https://new.example.com$request_uri; }
}


















