nginx可通过map提取自定义参数(如$arg_uid)构造稳定hash_key,再在upstream中用hash $hash_key consistent实现一致性负载均衡;支持header、cookie及多字段拼接,需配合日志验证键值稳定性。

Nginx 本身不支持直接对任意自定义请求参数(比如 ?uid=123 或 Header: X-User-ID)做哈希分发,但可以通过 hash 指令配合 map、set 或内置变量,提取并构造稳定哈希键,实现“基于自定义参数”的一致性负载均衡。
用 map 提取并标准化自定义参数
最常用且推荐的方式是先用 map 指令从请求中提取目标参数,并统一处理空值、非法值,避免哈希抖动:
map $arg_uid $hash_key {
"" "no-uid";
default "$arg_uid";
}
这样可确保:
• 参数缺失时固定映射为 no-uid,不导致后端漂移
• 非空 uid 直接作为哈希输入,保持同一 uid 总落到同一台后端
在 upstream 中使用 hash 指令绑定键
在 upstream 块中启用 hash,并指定刚才构造的变量:
upstream backend_cluster {
hash $hash_key consistent; # consistent 启用一致性哈希(可选)
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}
说明:
• hash $hash_key 表示对变量值做哈希,决定路由目标
• 加 consistent 可减少节点增减时的重映射范围(适合缓存类场景)
• 若省略 consistent,则为普通取模哈希,更简单但扩缩容时影响更大
支持 Header、Cookie 或组合字段的哈希键
除了 $arg_*,也可灵活组合其他来源:
- 按请求头哈希:
map $http_x_user_id $hash_key { ... } - 按 Cookie 值哈希:
map $cookie_sessionid $hash_key { ... } - 多字段拼接(如 uid + region):
set $hash_key "${arg_uid}_${arg_region}";(需在location内用set,再传入 upstream)
注意:set 在 location 中生效,不能直接用于 upstream 的 hash 参数;此时建议仍优先用 map(支持复杂逻辑且全局可用)。
验证与调试技巧
上线前建议加日志确认键值是否符合预期:
log_format hash_debug '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'hash_key:"$hash_key" upstream:"$upstream_addr"';
<p>access_log /var/log/nginx/hash-debug.log hash_debug;</p>
然后发起带不同参数的请求(如 ?uid=1001、?uid=1002),检查日志中 hash_key 和 upstream_addr 是否稳定对应。











