Nginx可通过hash指令结合URL参数(如user_id)实现稳定定向转发,支持一致性哈希与普通取模,配合map处理空值及特殊字符,适用于分库分表等场景。

提取 URL 参数作为 hash key
Nginx 原生支持从查询字符串中直接取参,用 `$arg_XXX` 变量即可:例如想按 user_id 分发:
-
set $shard_key $arg_user_id;—— 简单直接,适用于 GET 请求 - 若参数名含特殊字符(如
tenant-id),需用$args配合map解析,避免变量名非法 - 空值或缺失参数时,
$arg_user_id为空字符串,建议加默认 fallback:set $shard_key $arg_user_id;if ($shard_key = "") { set $shard_key "default"; }(注意:if 在 location 外不推荐,更稳妥用map)
配置 upstream 使用 hash 转发
在 upstream 块中启用 hash,并指定 key 变量:
-
hash $shard_key consistent;—— 推荐一致性哈希,节点增减影响小(要求 Nginx ≥ 1.19.0) -
hash $shard_key;—— 普通取模哈希,简单高效,但后端数量变化时映射会大面积漂移 - 确保 upstream 中的 server 地址稳定(不建议用域名,避免 DNS 缓存导致 weight/resolve 不一致)
完整配置示例
以下是一个基于 user_id 的定向代理配置片段:
map $arg_user_id $shard_key {
"" "fallback";
default $arg_user_id;
}
upstream db_proxy {
hash $shard_key consistent;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}
server {
listen 80;
location /api/ {
proxy_pass http://db_proxy;
proxy_set_header X-Real-IP $remote_addr;
}
}
说明:map 比 if 更安全高效;consistent 保证扩缩容时仅少量请求重路由;真实分库分表仍由后端中间件(如 ShardingSphere)完成,Nginx 只做前置路由。
注意事项与常见问题
-
POST 请求无法直接读 body:Nginx 默认不解析请求体,若必须依赖 POST 中的 user_id,应推动前端改用 URL 参数或 Header(如
X-Shard-Key)透传 -
key 大小写敏感:
user_id=ABC和user_id=abc被视为不同 key,必要时可用lowercase或正则归一化 - 避免 key 泄露风险:不要把敏感字段(如身份证号)直接作 hash key,建议使用脱敏后的 ID 或业务唯一标识
-
测试验证方法:用 curl 多次请求相同 user_id,观察
proxy_pass日志中的 upstream 地址是否一致


















