有个给某大客户(游戏下载类)的特殊需求设计,因为文件大小差距很大——估计是大版本和补丁的区别——又走的是同一个域名,而squid在响应比较大的文件时,尤其是初次下载
时,性能比较差,所以拆成两组服务器,squid服务于较小的文件,通过pull方式从peer层获取,nginx服务于较大的文件,通过push方式由peer层分发同步。外部发布域名一
律解析到squid服务器组上,请求透传到peer层的nginx,nginx分析这个url的content-length,如果大于阈值,则不返回文件,而是302到nginx服务器组的独立域名下的相应
url去。
注意:
nginx的内部变量里有一个$content-length,是不能用在这里的,官方wiki是这么解释这个变量的:”This variable is equal to line Content-Length in the
header of request”。
可见,这个变量是请求头的内容,一般见于POST请求用来限定POST信息的长度;而不是我们需要的响应头的内容。
最后是修改了nginx的src完成的功能。
其实可以使用http_perl_module完成的。而且还可以扩展302跳转的功能,把独立域名改成直接通过remote_addr定向到最近IP上。
以下内容仅限测试与学习使用。
首先,在nginx.conf中配置:
然后,在perl/SizeDiff.pm文件中,如下:
基本就是这样子,之前还考虑过如果不是push方式,可以在perl里考虑使用LWP获取header,不过仔细想想:
第一,万一源站开启了chunked获取不到content-length呢?
第二,就算可以,如果一个文件是1个G,那再去下载这1个G的文件下来,这个perl进程肯定挂了——官方wiki里可是连DNS解析时间都认为太长……也就是说,这个设想不适合在
peer层,而是在loadbalance的角色,通过lwp的header结果,小文件upstream到后端的squid,大文件location到另外的nginx。
另一个可改进之处,就是self->location前面,可以结合Net::IP::Match::Regexp模块或者自己完成的类似功能,来针对self->remote_addr选择最近的服务器组IP,最后返回
location(“http://$ip$uri”)。
闲来神笔,仅作参考,呵呵。
不妨作为研究nginx与squid的文档吧,脚本学堂,祝大家学习进步。