PS:由于公司图片存储使用的是FastDFS分布式文件系统,而且我一直参与其中的运维及其技术开发使用,在使用发现FastDFS虽然通过按照组域名的nginx插件访问图片减少请求压力,但是通常热点图片(大部分是最近上传到服务器上的图片)都聚集在一台服务器上,访问时表现在其单台服务器的IO过大.解决办法很多,如FastDFS同组内增加机器做负载或者前端增加cache层(varnish代理访问)缓存图片资源加快分发.经过几天的varnish研究并使用.下面详细介绍一下varnish
-
环境变量初始化
# vi .bashrc alias worksrc='cd /usr/local/src;ls' alias workvarnish='cd /usr/local/varnish;ls' 配置生效 # source .bashrc
-
Varnish 安装
-
安装 varnish
CentOS6.2 系统环境下的依耐关系
yum –y install automake autoconf libtool ncurses-devel libxslt groff pcre-devel pkgconfig
下载编译 Varnish
官网下载地址https://www.varnish-cache.org/releases/varnish-cache-3.0.3#安装方式1.源码编译(建议安装方式,能够自定义安装路径,下面介绍的是方式) worksrc; wget http://repo.varnish-cache.org/source/varnish-3.0.3.tar.gz; tar -zxvf varnish-3.0.3.tar.gz; cd varnish-3.0.3; ./configure --prefix=/usr/local/varnish; make && make install; #服务启动脚本转移至/etc/init.d下 cp ./redhat/varnish.initrc /etc/init.d/varnish #服务端启动参数配置脚本移至/etc/sysconfig下 cp ./redhat/varnish.sysconfig /etc/sysconfig/varnish #重载vcl配置的应用程序移至/usr/bin/下 cp ./redhat/varnish_reload_vcl /usr/bin/varnish_reload_vcl #varnish缓存存取策略配置文件备份 cp /usr/local/varnish/etc/varnish/default.vcl /usr/local/varnish/etc/varnish/vcl.conf # #安装方式2.rpm包安装(自动安装,比较方便) rpm --nosignature -i http://repo.varnish-cache.org/redhat/varnish-3.0/el5/noarch/varnish-release-3.0-1.noarch.rpm yum install varnish #--nosignature:想要略过数字证书的检查时,可以使用这个参数 #-i:install的意思
安装方式1的路径刨析:
/etc/init.d/varnish #服务启动脚本 /etc/sysconfig/varnish #服务端启动参数配置脚本 /usr/bin/varnish_reload_vcl #重载vcl配置的应用程序 /usr/local/varnish/etc/varnish #默认配置文件存放路径 /usr/local/varnish/etc/varnish/vcl.conf #varnish缓存存取策略配置文件 /usr/local/varnish/sbin/varnishd #varnish应用程序
-
设置varnish运行的用户和cache文件存储目录
/usr/sbin/groupadd varnish /usr/sbin/useradd -g varnish varnish mkdir -p /home/varnish/data chown -R varnish:varnish /home/varnish/data
-
varnish 启动脚本修改
“exec”用于指定varnish应用服务程序路径
“config”用于指定varnish服务启动参数脚本文件路径
“reload_exec”用于指定重载vcl配置的应用程序#vim /etc/init.d/varnish retval=0 pidfile=/var/run/varnish.pid # exec="/usr/sbin/varnishd" => "/usr/local/varnish/sbin/varnishd" reload_exec="/usr/bin/varnish_reload_vcl" prog="varnishd" config="/etc/sysconfig/varnish" lockfile="/var/lock/subsys/varnish"
启动 Varnsih 及自定义平滑重启脚本
# /etc/init.d/varnish Usage:/etc/init.d/varnish {start|stop|status|restart|condrestart|try-restart|reload|force-reload}
Varnish 如果用restart重启的话,那么之前所有的缓存都会丢失,造成回源压力大,甚至源挂掉,如果我们更改了 VCL 配置,又需要生效,那么需要平滑重启(reload)
#检测配置文件是否存在错误 /usr/local/varnish/sbin/varnishd -C -f /usr/local/varnish/etc/varnish/vcl.conf
-
服务端启动参数配置脚本分析
vim /etc/sysconfig/varnish # Configuration file for varnish # # /etc/init.d/varnish expects the variable $DAEMON_OPTS to be set from this # shell script fragment. # # Maximum number of open files (for ulimit -n) NFILES=131072 # Locked shared memory (for ulimit -l) # Default log size is 82MB + header MEMLOCK=82000 # Maximum size of corefile (for ulimit -c). Default in Fedora is 0 # DAEMON_COREFILE_LIMIT="unlimited" # Set this to 1 to make init script reload try to switch vcl without restart. # To make this work, you need to set the following variables # explicit: VARNISH_VCL_CONF, VARNISH_ADMIN_LISTEN_ADDRESS, # VARNISH_ADMIN_LISTEN_PORT, VARNISH_SECRET_FILE, or in short, # use Alternative 3, Advanced configuration, below RELOAD_VCL=1 ## Alternative 3, Advanced configuration # # See varnishd(1) for more information. # # # Main configuration file. You probably want to change it # varnish缓存存取策略配置文件(修改处) VARNISH_VCL_CONF=/usr/local/varnish/etc/varnish/vcl.conf # # # Default address and port to bind to # # Blank address means all IPv4 and IPv6 interfaces, otherwise specify # # a host name, an IPv4 dotted quad, or an IPv6 address in brackets. # 本地监听端口 # VARNISH_LISTEN_ADDRESS= VARNISH_LISTEN_PORT=80 # # # Telnet admin interface listen address and port #设定varnish的telnet管理地址及其端口 VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 VARNISH_ADMIN_LISTEN_PORT=3500 # # # Shared secret file for admin interface共享密钥文件 VARNISH_SECRET_FILE=/etc/varnish/secret # # # The minimum number of worker threads to start指定启动的最小的线程数 VARNISH_MIN_THREADS=50 # # # The Maximum number of worker threads to start指定启动的最大的线程数 VARNISH_MAX_THREADS=1000 # # # Idle timeout for worker threads线程超时时间 VARNISH_THREAD_TIMEOUT=120 # # # Cache file location 缓存文件存储位置(上例新建目录) VARNISH_STORAGE_FILE=/home/varnish/data/varnish_storage.bin # # # Cache file size: in bytes, optionally using k / M / G / T suffix, # # or in percentage of available disk space using the % suffix. #缓存文件的大小(单位:k / M / G / T) VARNISH_STORAGE_SIZE=1G # # # Backend storage specification #varnish的缓存存储方式有file和malloc两种方式 VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}" #VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}" # # # Default TTL used when the backend does not specify one #指定默认的TTL值,超过这个值得数据包将被丢弃 VARNISH_TTL=120 # # # DAEMON_OPTS is used by the init script. If you add or remove options, make # # sure you update this section, too. DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \ -f ${VARNISH_VCL_CONF} \ -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \ -t ${VARNISH_TTL} \ -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \ -u varnish -g varnish \ #-S ${VARNISH_SECRET_FILE} \ -s ${VARNISH_STORAGE}" # ## Alternative 4, Do It Yourself. See varnishd(1) for more information. # # DAEMON_OPTS=""
由配置可以看出,可以定义一些变量值如VARNISH_LISTEN_ADDRESS,VARNISH_LISTEN_PORTVARNISH_VCL_CONF等组装DAEMON_OPTS变量.下面是DAEMON_OPTS常用参数的使用方法和含义
#varnish语法 #/usr/local/varnish/sbin/varnishd --help -a address:port 表示varnish监听所有IP发给port端口的http请求,在生产环境下varnish默认的监听80 -b address:port 表示后端服务器地址及其端口(和-f不能同时使用) -f file varnish缓存存取策略配置文件(和-b不能同时使用) -T address:port 设定varnish的telnet管理地址及其端口,主要用来清除缓存 -S 清除缓存时要进行auth验证 -t 指定缺省的TTL值,表示DNS记录在DNS服务器上缓存时间 -d 表示使用debug调试模式 -p param=value 指定服务器参数,用来优化varnish性能 -P file Varnish进程PID文件存放路径 -n dir 指定varnish的工作目录 -s 指定varnish缓存内容的存储类型和存储容量,常用的方式有:"-s file,
, " -w 最小,最大线程和超时时间 例如:-w5,51200,30,这里需要说明下,在varnish2.0版本以后,最小启动的线程数不能设定过大,设置过大,会导致varnish运行异常缓慢. -V 显示varnish版本号和版权信息 如果启动参数是有使用-S /etc/varnish/secret这个参数的,那么在清空缓存时候必须指定此参数.如果清除缓存时候不指定此参数varnish会提示Authentication required,缓存的命令就是:varnishadm -T 127.0.0.1:3500 -S /etc/varnish/secret ban.url xxx
同时监听两个端口,80和8080 :-a 0.0.0.0:8080,0.0.0.0:80
-s 选项用来确定 varnish 使用的存储类型和存储容量.80%是指占用磁盘 80%的空间 -
分析/etc/sysconfig/varnish中的VARNISH_VCL_CONF(即缓存存取策略配置文件)
处理过程大致分为如下几个步骤:
(1) Receive状态,也就是初始url请求处理的入口状态,根据VCL规则判断该请求应该是Pass或Pipe,或者进入Lookup(本地查询).
(2) Lookup状态,进入此状态后,会在hash表中查找数据,若找到,则进入Hit状态,否则进入miss状态.
(3) Pass状态,在此状态下,会进入后端请求,即进入fetch状态.
(4) Fetch状态,在Fetch状态下,对请求进行后端服务器的获取,发送请求,获得数据,并进行本地的存储.
(5) Deliver状态, 将获取到的数据发送给客户端,然后完成本次请求.配置文件案例
#本机ip:192.168.12.25 varnish端口:80 #后端主机(backend)定义为webserver :192.168.12.26负责提供php解析服务 backend webserver { .host = "192.168.12.26"; .port = "80"; } #url请求处理入口 sub vcl_recv { ##start 固定的处理方式,不需要修改## if (req.http.x-forwarded-for) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip; } else { set req.http.X-Forwarded-For = client.ip; } #如果请求的类型不是GET、HEAD、PUT、POST、TRACE、OPTIONS或DELETE时,则进 #入pipe模式。注意这里是"&&"关系 if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" && req.request != "OPTIONS" && req.request != "DELETE") { return (pipe); } #如果请求的类型不是GET或HEAD,则进入pass模式 if (req.request != "GET" && req.request != "HEAD") { return (pass); } ##end 固定的处理方式## # ##start 开始对进入的url做解析并判断下一步是Pass或Pipe,或者进入Lookup(本地查询)## #对ixdba.net或者ixdba.cn两个域名进行缓存加速。这是个泛域名的概念,也就是将所有以ixdba.net或者ixdba.cn结尾的域名除了以(.php结尾以及带有?的URL)都进行缓存 if (req.http.host ~ "^(.*).ixdba.net" || req.http.host ~ "^(.*).ixdba.cn") { set req.backend = webserver; #对以.php结尾以及带有?的URL,直接从后端服务器读取内容,不进行缓存,直接pass if (req.url ~ "\.(php)($|\?)") { return (pass); } } ##end## # //上面规则之外的查询的都去cache里查找 return (lookup); } sub vcl_pipe { return (pipe); } sub vcl_pass { return (pass); } sub vcl_hash { set req.hash += req.url; if (req.http.host) { set req.hash += req.http.host; } else { set req.hash += server.ip; } return (hash); } sub vcl_hit { if (!obj.cacheable) { return (pass); } return (deliver); } sub vcl_miss { return (fetch); } #对在vcl_recv中获得的后端服务器数据,判断是否进行本地的存储 sub vcl_fetch { if (!beresp.cacheable) { return (pass); } if (beresp.http.Set-Cookie) { return (pass); } #当url中包含servlet时,不进行缓存 if (req.url ~ "^/servlet/") { return (pass); } #如果请求类型是GET,并且请求的URL中包含upload,那么就进行缓存,缓存的时间是300秒,即5分钟 if (req.request == "GET" && req.url ~ "^/upload(.*)$") { set beresp.ttl = 300s; } #当请求类型是GET,并且请求的URL以png、xsl、xml、gif、css、js等结尾时,进行缓存,缓存时间为600秒 if (req.request == "GET" && req.url ~ "\.(png|xsl|xml|pdf|ppt|doc|docx|chm|rar|zip|bmp|jpeg|swf|ico|mp3|mp4|rmvb|ogg|mov|avi|wmv|swf|txt|png|gif|jpg|css|js|html|htm)$") { set beresp.ttl = 600s; } return (deliver); } #下面添加一个Header标识,以判断缓存是否命中 sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT from www.ixdba.net"; } else { set resp.http.X-Cache = "MISS from www.ixdba.net"; } return (deliver); }
-
总结:
参考:
varnish官网
高性能HTTP加速器Varnish(管理维护篇)