跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何利用 hash $request_uri 实现基于 URL 路径的定向流量分发

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

相关文章