nginx 做 url 的 hash 时,做动态和静态的 hash 时需要多多注意。因为动态和静态的文件表现出来的不一样。
静态文件 Nginx 的 Hash 处理
静态的文件的源网站的,特点文件静态,大小基本是几种类型的大小,每个节点存的文件,大多不一样,基本img1,img2,img3.这三个节点存的不一样的文件。
如下:
http://mp4.phpabc.cn/index/8277e0910d750195b448797616e091ad.mp4?key=92eb5ffee6ae2fec3ad71c777531578f
http://flv.phpabc.cn/home/4a8a08f09d37b73795649038408b5f33.flv?key=92eb5ffee6ae2fec3ad71c777531578f
http://f4v.phpabc.cn/user/0cc175b9c0f1b6a831c399e269772661.f4v?key=92eb5ffee6ae2fec3ad71c777531578f
http://mp4.phpabc.cn/index/8277e0910d750195b448797616e091ad.mp4?key=92eb5ffee6ae2fec3ad71c777531578f
http://flv.phpabc.cn/home/4a8a08f09d37b73795649038408b5f33.flv?key=92eb5ffee6ae2fec3ad71c777531578f
http://f4v.phpabc.cn/user/0cc175b9c0f1b6a831c399e269772661.f4v?key=92eb5ffee6ae2fec3ad71c777531578f
静态文件,这样设计不只为了能处理更多请求,还为了存储的可扩展。
所以针对这二种文件,在 Url 中做 Url 的 hash 时, nginx 要分别处理,因为为了防盗链之类的原因,还有存储的原因。不能给 key 计算到整个 nginx 的 hash 的算法中。当给整个 Url 加入到 Hash 的算法中时,因为 key 是变化的内容。下次 key 变化后,你 Nginx 重向的服务器就发生了变化,这样当然是不可取的。
所以在静态文件中,建议 Nginx 的 Hash 的算法修改为
hash $uri; # uri 为 Nginx 的内部变量,表示没有 ? 的 url.
hash $uri; # uri 为 Nginx 的内部变量,表示没有 ? 的 url.
这样,防盗链之类的算法怎么改变,都不会影响到 Nginx 的重定向.
动态文件 Nginx 的 Hash 处理
但动态的,所有服务器,大多是所有服务器可以处理所有动态的内容,基本没有主从之分,这主要是为了可以处理更加多的请求。
http://web2.phpabc.cn/index.php?search=12
http://web1.phpabc.cn/index.php?search=12
http://web2.phpabc.cn/index.php?search=12
http://web1.phpabc.cn/index.php?search=12
所以这种的时候,nginx 建议设置成
hash $request_uri; # request_uri 为 Nginx 的内部变量,表示有 ? 的 url.
hash $request_uri; # request_uri 为 Nginx 的内部变量,表示有 ? 的 url.
当这样设置时,同样的请求,可以被平均分到多台后端的服务器。更加方便动态文件的处理。
其它情况 Nginx 的 Hash 处理
在静态文件时,还有一种变化的防盗链的算法。如下。
http://mp4.phpabc.cb/92eb5ffee6ae2fec3ad71c777531578f/index/8277e0910d750195b448797616e091ad.mp4
http://flv.phpabc.cn/92eb5ffee6ae2fec3ad71c777531578f/home/4a8a08f09d37b73795649038408b5f33.flv
http://f4v.phpabc.cn/92eb5ffee6ae2fec3ad71c777531578f/user/0cc175b9c0f1b6a831c399e269772661.f4v
http://mp4.phpabc.cb/92eb5ffee6ae2fec3ad71c777531578f/index/8277e0910d750195b448797616e091ad.mp4
http://flv.phpabc.cn/92eb5ffee6ae2fec3ad71c777531578f/home/4a8a08f09d37b73795649038408b5f33.flv
http://f4v.phpabc.cn/92eb5ffee6ae2fec3ad71c777531578f/user/0cc175b9c0f1b6a831c399e269772661.f4v
在这种情况下,发现防盗链的算法的 key 内容是直接放到 Url 中的第一个部分的。这样处理起来就有点麻烦,因为 request_uri 和 uri 都是不能正常生成好用的 Hash 结果来用的。
这只能使用变态点的方法.如下
server
{
listen 80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
if ($uri ~* "\/([^\/]+)$" ){
set $filename $1;
}
location /
{
proxy_pass http://default;
}
}
upstream default
{
hash $filename;
server 121.xx.xxx.1;# node1
server 121.xx.xxx.2;# node2
server 121.xx.xxx.3;# node3
}
server
{
listen 80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
if ($uri ~* "\/([^\/]+)$" ){
set $filename $1;
}
location /
{
proxy_pass http://default;
}
}
upstream default
{
hash $filename;
server 121.xx.xxx.1;# node1
server 121.xx.xxx.2;# node2
server 121.xx.xxx.3;# node3
}
这个时候 ,我使用标准的 Perl 的正则,来取得最后一个 / 后的文件名。如上面的 0cc175b9c0f1b6a831c399e269772661.f4v。 然后我对这个文件名来做 hash .
这样,无论中间的防盗链的 key 怎么修改,我都能正常使用。
在 nginx 中的 set 的功能相当好用,可以定制自己要的变量内容。给这个自定的 $filename 变量,交给 Hash 算法来计算。