nginx基于请求头实现负载切换的核心是用map指令提取请求头值并映射为变量,再结合预定义upstream组和动态proxy_pass完成路由;map须置于http块顶层,proxy_pass中变量需严格匹配upstream名称前缀,default兜底值必须对应有效upstream。

在 Nginx 代理中实现基于请求头的负载切换,核心是利用 map 指令提取请求头值,再结合 upstream 和 proxy_pass 动态路由到不同后端组。这不是简单的 if 判断,而是通过变量映射 + 条件 upstream 选择来实现稳定、高性能的分流。
用 map 提取并分类请求头值
Nginx 不允许在 location 中直接用 if 跳转 upstream,但支持在 http 块中用 map 构建映射变量。例如,根据 X-Env 请求头决定走测试还是生产后端:
map $http_x_env $backend_group {
default "prod";
~*[tT]est "test";
~*[sS]taging "staging";
}
说明:
• $http_x_env 自动对应请求头 X-Env(下划线转横线,全小写)
• 支持正则匹配(如 ~*[tT]est 忽略大小写匹配 test/test1/Test 等)
• 匹配失败走 default,建议始终设置兜底值
定义多个 upstream 组
为不同环境或策略准备独立的 upstream 块,便于维护和健康检查:
upstream backend_prod {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
upstream backend_test {
server 10.0.2.5:8080;
}
upstream backend_staging {
server 10.0.3.20:8080 weight=2;
server 10.0.3.21:8080;
}
注意:
• 每个 upstream 可配置自己的负载策略(least_conn、ip_hash 等)
• 可单独启用健康检查(需配合 nginx-plus 或开源版第三方模块如 nginx_upstream_check_module)
在 location 中动态 proxy_pass
使用变量名作为 upstream 名称,Nginx 会在运行时解析该变量指向的实际 upstream:
server {
listen 80;
location /api/ {
proxy_pass http://backend_$backend_group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
关键点:
• proxy_pass http://backend_$backend_group 中的 $backend_group 必须与 upstream 名前缀严格一致
• 不支持拼接复杂字符串(如 http://backend-$backend_group-v1),变量必须直接构成合法 upstream 名
• 若变量值不匹配任何 upstream,Nginx 会返回 502 错误,务必保证 map 的 default 有对应 upstream
验证与调试技巧
上线前快速确认逻辑是否生效:
- 用 curl 添加自定义头测试:
curl -H "X-Env: test" http://your-domain/api/health - 开启 Nginx error log 的 debug 级别(临时),查看变量展开日志:
error_log /var/log/nginx/error.log debug; - 在响应头中注入调试信息(仅开发环境):
add_header X-Backend-Used $backend_group; - 避免在 map 中使用未定义变量或嵌套 map,Nginx 不支持递归解析
不复杂但容易忽略:所有 map 必须定义在 http 块顶层,不能放在 server 或 location 内;变量名区分大小写,且不能含短横线(-)。











