Nginx 轮询本身不支持按参数分流,但可通过 map 模块预处理请求参数(如 user_id、app_type),映射为 upstream 名称或分片标识,再结合各 upstream 内部轮询实现条件化负载均衡。

Nginx 的轮询(round-robin)本身是无状态的、均匀分配请求的默认策略,它不直接支持“按请求参数分流”。但通过 map 模块预处理参数,再结合 upstream 的分组或变量路由,就能实现「看似轮询、实则带条件」的负载均衡效果——本质是把参数映射为 upstream 名称或权重标识,再交由对应后端组执行真正的轮询。
用 map 提取并分类请求参数
map 是 Nginx 的变量映射模块,可在请求进入 proxy_pass 前,根据 query string 或 header 提取值并生成新变量。例如,按 user_id 的哈希前缀或业务类型路由:
注意:map 必须定义在 http 块顶层,不能在 server 或 location 内
http {
map $arg_user_id $backend_group {
~^1[0-9]{4} group_a;
~^2[0-9]{4} group_b;
default group_default;
}
<pre class="brush:php;toolbar:false;">map $arg_app_type $upstream_name {
"mobile" upstream_mobile;
"web" upstream_web;
"" upstream_default; # 空值兜底
default upstream_default;
}}
为不同分组配置独立 upstream(启用轮询)
每个 map 输出的分组名,对应一个独立的 upstream 块。这些 upstream 内部仍使用默认轮询算法,保证组内服务器均摊压力:
upstream upstream_mobile {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
<p>upstream upstream_web {
server 10.0.1.20:8080;
server 10.0.1.21:8080;
}</p><p>upstream upstream_default {
server 10.0.1.30:8080;
server 10.0.1.31:8080;
}在 location 中动态选择 upstream
利用 map 生成的变量作为 proxy_pass 的目标,Nginx 会自动调用对应 upstream 的轮询逻辑:
server {
location /api/ {
proxy_pass http://$upstream_name;
proxy_set_header Host $host;
}
}这样,?app_type=mobile 的请求始终进入 upstream_mobile,该组内两台机器仍按轮询分发;而参数变化时,流量自动切换到另一组,各组内部保持轮询公平性。
进阶技巧:用 hash + map 实现一致性分流
若需相同参数总是落到同一组(比如避免 session 散布),可在 map 中引入 hash 计算,再模运算分桶:
map $arg_user_id $shard_id {
default "";
~^(?<uid>\d+) "$uid";
}
<h1>注意:需启用 ngx_http_map_module 和 hash 支持</h1><p>map $shard_id $backend_shard {
"" shard_0;
~^(?<h>\d+)(?<r>\d{2}) $r; # 取 uid 后两位做分片标识
}</p><p>upstream shard_0 { server 10.0.2.1:8080; }
upstream shard_1 { server 10.0.2.2:8080; }</p><h1>……可扩展至 shard_99</h1><p>配合 proxy_pass http://shard_$backend_shard;,就能让 user_id 尾号相同的请求稳定落在同一 upstream 组,组内继续轮询。


















