hash $request_uri可实现基于完整URI(含查询参数)的一致性哈希分发,确保相同URL固定路由至同一后端,适用于缓存亲和、灰度测试等场景;需注意其区分大小写、不自动解码、参数顺序敏感等特性,推荐加consistent提升伸缩稳定性。
利用
可以在 Nginx 中实现基于完整请求 URI(含查询参数)的一致性哈希分发,适合需要将相同 URL 长期固定到同一后端的场景,比如缓存亲和、灰度测试或避免重复计算。
理解 hash $request_uri 的行为特点
是 Nginx 内置变量,值为原始请求行中的 URI(例如
),
包含路径和完整查询字符串,且不进行解码或标准化
。使用
指令对其做哈希时:
相同 URI 字符串每次计算出的哈希值一致,保证同一 URL 总落到同一 upstream server
URI 中任意字符差异(如大小写、空格、编码形式、参数顺序)都会导致哈希结果不同
后端节点增减时,部分 URI 映射会变动(标准哈希特性,非一致性哈希);如需更稳定的映射,应改用
配置示例:基础 URI 哈希分发
在
块中启用哈希,并在
或
中调用:
然后在 server 块中代理请求:
此时
和
被视为两个不同 URI,可能分到不同后端——若需忽略参数顺序,需先重写 URI 统一格式。
增强可控性:预处理 URI 再哈希
为提升分发合理性,常对
做归一化处理。例如:
去掉查询参数:用
替代(仅路径,不含 ? 及之后内容)
统一小写:通过
指令转换:
再对
哈希(注意:Nginx 本身不支持直接 lowercase URI,需借助 Lua 或外部模块;简单场景可用
+
手动拼接并排序参数)
排除特定参数(如跟踪用的
、
):用
+
构造净化后的变量,再哈希
适用与慎用场景说明
适合:
– API 级别缓存亲和(如某商品详情页总由同一节点渲染并缓存)
– 后端无状态但需减少跨节点重复初始化(如冷启动耗时服务)
– A/B 测试中按 URL 分流,确保用户多次访问同 URL 始终看到同一版本
慎用:
– URI 参数高度动态(如带时间戳、随机数、签名)会导致哈希完全散列,失去分发意义
– 后端节点频繁扩缩容,普通
会造成大量 URI 重映射,建议加
关键字
– 需要按用户或设备分流时,
不含身份信息,应改用
或
hash $request_uri$request_uri/api/user?id=123&v=2hashhash $request_uri consistent;upstreamserverlocationupstream backend_cluster {
hash $request_uri;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}location / {
proxy_pass http://backend_cluster;
proxy_set_header Host $host;
}/search?q=nginx&page=1/search?page=1&q=nginx$request_uri$urimapmap $request_uri $norm_uri {
~^(?[^?]*)(?:\?(?.*))?$ ${m1}?${m2};
} $norm_uri$uri$argsutm_*ts=ifsethashconsistent$request_uri$cookie_uid$http_x_forwarded_for