Nginx中rewrite在多环境分流中不直接负载均衡,而是配合if、set、return等指令,基于域名、请求头、Cookie或路径条件实现重定向或URI改写,从而将流量导向对应环境后端。

在多环境测试(如 dev / staging / prod)中,用 Nginx rewrite 实现自动化流量分流,核心不是靠 rewrite 做“分流”,而是结合 if 判断 + 变量 + rewrite 或 return,配合域名、请求头、Cookie 等条件,把请求导向不同后端或重定向到对应环境域名。rewrite 本身不直接做负载均衡式分流,但它能灵活改写 URI 或触发跳转,是实现环境路由的关键一环。
明确目标:rewrite 在多环境分流中的角色
rewrite 不替代 proxy_pass,它主要负责:
- 根据条件将请求重定向到对应环境子域名(如 dev.example.com → staging.example.com)
- 改写路径前缀,让同一套配置适配不同环境的 API 路由规则(如 /api/ → /staging/api/)
- 配合 set 指令预设变量,供后续 location 或 proxy_pass 动态引用
按域名自动跳转到对应环境
最常见做法:用多个 server 块分别监听各测试域名,再用 rewrite 或 return 统一处理跳转逻辑。例如:
# 将所有非生产域名的请求,302 临时跳转到对应环境
server {
listen 80;
server_name ~^(dev|staging|test)\.example\.com$;
<pre class='brush:php;toolbar:false;'># 提取子域名作为环境标识
if ($host ~ ^(?<env>dev|staging|test)\.example\.com$) {
set $target_env $env;
}
# 根据环境跳转(保留原始路径和参数)
return 302 https://$target_env.example.com$request_uri;}
这样访问 dev.example.com/path?x=1 会跳转到 https://dev.example.com/path?x=1;若想跳到统一网关或内部服务,可改为:rewrite ^(.*)$ https://gateway.internal/$target_env break;
按请求头或 Cookie 切换环境(灰度测试)
适合需要对部分用户启用新环境的情况。rewrite 配合 if 和内置变量即可实现:
server {
listen 80;
server_name example.com;
<pre class='brush:php;toolbar:false;'># 若请求头带 X-Env: staging,重写 Host 并转发
if ($http_x_env = "staging") {
set $upstream_backend "http://127.0.0.1:8081";
set $upstream_host "staging.example.com";
rewrite ^(.*)$ $1 break;
}
# 否则走默认 prod
if ($http_x_env != "staging") {
set $upstream_backend "http://127.0.0.1:8080";
set $upstream_host "example.com";
}
location / {
proxy_pass $upstream_backend;
proxy_set_header Host $upstream_host;
proxy_set_header X-Real-IP $remote_addr;
}}
注意:if 在 location 外使用有局限,更稳妥的做法是用 map 指令预定义变量(推荐),但 rewrite 仍可用于路径改写环节,比如:
map $http_x_env $backend_port {
default 8080;
"staging" 8081;
"dev" 8082;
}
# ……然后在 location 中:
proxy_pass http://127.0.0.1:$backend_port;路径级环境隔离(同一域名下区分环境)
例如所有请求带 /dev/xxx 自动转给开发服务,/staging/xxx 转给预发服务:
server {
listen 80;
server_name example.com;
<pre class='brush:php;toolbar:false;'>location /dev/ {
rewrite ^/dev/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
}
location /staging/ {
rewrite ^/staging/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:3002;
proxy_set_header Host $host;
}
location / {
proxy_pass http://127.0.0.1:3000; # 默认 prod
}}
这里 rewrite 的作用是剥离前缀,避免后端收到带 /dev/ 的路径;break 确保不重复匹配其他 location。


















