高性能HTTP加速器Varnish

PS:由于公司图片存储使用的是FastDFS分布式文件系统,而且我一直参与其中的运维及其技术开发使用,在使用发现FastDFS虽然通过按照组域名的nginx插件访问图片减少请求压力,但是通常热点图片(大部分是最近上传到服务器上的图片)都聚集在一台服务器上,访问时表现在其单台服务器的IO过大.解决办法很多,如FastDFS同组内增加机器做负载或者前端增加cache层(varnish代理访问)缓存图片资源加快分发.经过几天的varnish研究并使用.下面详细介绍一下varnish

  1. 环境变量初始化

        # vi .bashrc
        alias  worksrc='cd /usr/local/src;ls'
        alias  workvarnish='cd /usr/local/varnish;ls'
        配置生效
        # source .bashrc
        
  2. Varnish 安装


    1. 安装 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应用程序
                  
    2. 设置varnish运行的用户和cache文件存储目录

              /usr/sbin/groupadd varnish
              /usr/sbin/useradd -g varnish varnish
              mkdir -p /home/varnish/data
              chown -R varnish:varnish /home/varnish/data
              
    3. 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
                  
    4. 服务端启动参数配置脚本分析

                  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%的空间

    5. 分析/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(管理维护篇)

相关文章
  1. 对Web静态资源缓存自动更新的思考与实践的总结
  2. 单机多git帐号的访问详解案例
  3. CentOS 6.5安装部署SVN 1.8.13
  4. php-redis扩展
  5. Redis安装部署
  6. gearman应用-分布式图库系统设计
本站版权
1、本站所有主题由该文章作者发表,该文章作者与尘埃享有文章相关版权
2、其他单位或个人使用、转载或引用本文时必须同时征得该文章作者和尘埃的同意
3、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
4、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
5、原文链接:
二维码
Posted in Cache/File存储, linux技术, Varnish
Comments are closed.