nginx的性能很好,插件也多。当Nginx作为文件下载服务的反向代理,用户请求一个非常大的文件的时候,它会一直占满反向代理服务器与后端主机之间的带宽。因为nginx一次获取整个文件,缓冲获取到的文件,导致客户端不能马上读取到。带宽使用和iowait会很高。
当时经验不足,突然遇到这个问题,想到的第一个办法就是预分发:
在服务端用脚本监听源nginx的根目录;
一旦有文件变化就直接遍历边缘nginx,用wget下载此文件;
在边缘nginx配置nginx proxy_store或proxy_cache模块,这样文件就被缓存到边缘节点了,达到了预分发的效果。
这个办法理论上是没有问题的,可实际上很难保证在文件预分发完成之前禁止回源。
而恰巧360的开源项目中的ngx_http_subrange_module模块解决了这个问题:
ngx_http_subrange_module就是为了解决这个问题,它能分割HTTP requests。将大数据量的HTTP请求切分为多个子请求,当下载一个1G的文件,subrange将从后端主机中下载文件块,比如先获取5M,然后再获取5M,直到客户端下载完整个文件。
http://www.oschina.net/p/ngx_http_subrange_module
下面是我原来方案使用的脚本:
#!/bin/sh echo "$0 is running...." #Configuration. According to the your case configuration to configure. ADDRLIST=("http://172.30.25.246:8090" "http://192.168.15.159:7091" "http://192.168.15.159:7092" "http://172.30.25.246:8090"); INOTIFYDIR="/home/diskf"; LOGDIR=`pwd`; #Default Configuration.Please don't change. RUNDIR=`pwd`; STARTTIME=0; NOWTIME=`date +%s`; FAILEDLIST=`./failedlist.txt`; #Make sure only one predist.sh is running! if [ -e pre.pid ] then echo "There is a pre.sh running!exit." exit 0 fi echo $$ > pre.pid; #clean cachedir and mkdir tmp rm -rf "${RUNDIR}/tmp/*"; mkdir -p ${RUNDIR}/tmp; if [ -e pre.star ] then STARTTIME=`cat pre.star` else tmptime=`date +%s`; ${tmptime}=${$tmptime-432000}; echo "${tmp}" fi echo ${NOWTIME} > pre.star function download() { for item in $@ do name=`echo $item | cut -d '|' -f1`; url=`echo $item | cut -d '|' -f2`; if [ -z $url ]; then exit 1; fi touch $name; wget "$url" -O "$STOREPATH$name" -a "$WGETLOGDIR" echo "------Status:$?-----"; if [ $?!=0 ]; then echo "Download $url failed!"; echo "$item" >> $FAILEDLIST; fi echo $url; done } function scandir() { local cur_dir parent_dir workdir workdir=$1 cd ${workdir} if [ ${workdir} = "/" ] then cur_dir="" else cur_dir=`pwd` fi for dirlist in $(ls ${cur_dir}) do if test -d ${dirlist};then cd ${dirlist} scandir ${cur_dir}/${dirlist} cd .. else #echo ${cur_dir}/${dirlist} a=`stat -c %Y ${cur_dir}/${dirlist}`; abs_dir=${cur_dir}/${dirlist}; if [ $STARTTIME -lt $a ] then for tmpaddr in ${ADDRLIST[@]} do touch "${RUNDIR}/tmp/${dirlist}"; #wget -b "${tmpaddr}${abs_dir#$INOTIFYDIR}" -O "${RUNDIR}/tmp/${dirlist}" -a "${LOGDIR}/wgetinfo.log"; wget "${tmpaddr}${abs_dir#$INOTIFYDIR}" -O "${RUNDIR}/tmp/${dirlist}" -a "${LOGDIR}/wgetinfo.log"; if [ $?!=0 ]; then echo "Download failed!"; echo "${tmpaddr}${abs_dir#$INOTIFYDIR}|${RUNDIR}/tmp/${dirlist}" >> $FAILEDLIST; fi echo "wget status:$?; filename:${RUNDIR}/tmp/${dirlist}"; #rm -rf "${RUNDIR}/tmp/${dirlist}"; done fi fi done } if test -d $INOTIFYDIR then #Download the files which dowload filed just now. items=`cat $FAILEDLIST`; echo "">"$FAILEDLIST"; download ${items}; #Scand dir a new loop. scandir $INOTIFYDIR elif test -f $INOTIFYDIR then echo "You set a file as INOTIFYDIR but not a directory,pleas reinput and try again" exit 1 else echo "The INOTIFYDIR isn't exist which you input,pls input a new one!!" exit 1 fi cd ${RUNDIR} rm -f pre.pid echo "$0 has been finished....."
END
转载请注明来源:https://www.cnblogs.com/bugutian/