若是有对以下的配置命令有不明晰的,附件有在下翻译的VCL手册,可以进行查阅!

1. 什么是varnish?

   1、varnish首先是一个反向代理服务器,其次才是一个web加速缓存服务器。它所缓存的对象是key/value(即键/值)的形式来存储的,通常情况下,键一般是指URL,而值就是URL问的具体的资源(或称为对象)。

   2、varnish的配置文件是由专门的VCL(即varnish 配置语言)来进行配置的。这种语言首先要先转换为C代码,然后在执行。

   3、varnish支持epoll、kqueue等这种高性能的I/O事件通知模型。

   4、 varnish的日志在它所申请的共享内存日志中。默认为80M,

2. varnish的原理

   1、varnish启动后包含两个进程,一个是management进程和child进程。

   2、management进程主要用来管理配置文件以及对子进程的监控和对varnish的初始化,而且提供了一个命令行管理接口等。

   3、child进程由几个不同类型的线程组成,比较典型的有:

       ● acceptor线程:用来接收新连接

       ● worker线程:具体工作的线程,一个线程对应一个连接会话。

       ● expiry线程:对过期的线程进程清除。

3. varnish支持的缓存存储类型:

       ● file:使用特定的文件存储所有的缓存数据,然后在通过mmap()这个系统调用将整个文件的数据映射到进程空间。不过,重启或停止varnish后,缓存的内容会消失,也就是说不能持久存储。

       ● malloc:使用malloc()系统调用在varnish启动的时候想内存申请固定大小的内存来缓存数据。

       ● persistent:还处于测试时期,不建议使用。

       注:存储类型使用-s参数来指定。

4. 安装与配置

   环境:CentOS6.5,iptables 和 selinux 为关闭状态。

   软件包:varnish-3.0.5-1.el6.x86_64.rpm

           varnish-docs-3.0.5-1.el6.x86_64.rpm

           varnish-libs-3.0.5-1.el6.x86_64.rpm

   下载地址:

       http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/

   前端:varnish服务器,两块网卡:

       eth0: 172.16.0.11

       eth1: 192.168.0.11

   后端:两台apache服务器,各一块网卡:

       web1: 192.168.0.12

       web2: 192.168.0.13

       网关:192.168.0.11

配置文件:

       目录:/etc/varnish

       文件:default.vcl

             secret #用于管理接口所使用的共享密钥文件

       脚本:/etc/rc.d/init.d/varnishd

       脚本配置文件:/etc/sysconfig/varnish #用于指定配置参数

           其中:-a <[hostname]:port> : 指定varnish服务监听的地址和端口

                 -f <filename> : 指定VCL文件路径

                 -p <parameter=value> : 用于调整参数值

                 -S <secretfile> : 命令行管理接口的认证加密文件

                 -T <hostname:port> : 指定管理的地址和接口

                 -s <storagetype,options> : 指定缓存对象的存储类型和位置,以及大小等

负载均衡支持的算法:

       ● round-robin : 没有额外的参数

       ● random :包含有两个参数:

           1、.weight :表示权重越大,对应的后端服务器接收的请求越多,可以对每个后端服务器进行设置。

           2、.retries : 用于定义查找后端健康服务器的次数。是对整个director进行设置的,其默认值为在director中定义的服务器的数量。

       ● hash :它是random的一个特殊变体,它使用缓存中的hash数据来进行调度,也就是说相同的URL的请求将会发往相同的web服务器。这种调度方法非常适合后端服务器还是缓存服务器的情况。

       ● client :它也是random的一个特殊变体。它使用client.identity来进行调度,此变量默认值是客户端的IP,但是可以在VCL中改变其值。使用这种算法,如果所有 请求的client.identity的值相同的话,那么统一客户端的请求都会发往同一个后端服务器。

       ● dns :它是根据客户端请求Host头部信息,在一个给定的后端服务器列表中进行查找 匹配的。(此算法用的不多,也不支持对后端服务的健康检测)

       ● fallback : 用来定义备用服务器,没有额外的参数。

       注意:先定义后调用,有先后顺序之分,只定义不调用会报错。比如,在定义director后必须在后面对其进行调用否则会发生编译错误。

1、将varnish的监听接口改为80

       vim /etc/sysconfig/varnish

           VARNISH_LISTEN_PORT=80

2、定义后端服务器

       backend web1 {

           .host = "192.168.0.12";

           .port = "80";

       }

       backend web2 {

           .host = "192.168.0.13";

           .port = "80";

       }

3、定义负载均衡director(即调度器)

       director webs round-robbin {

           { .backend = web1; }

           { .backend = web2; }

       }

4、调用上面定义的director

       sub vcl_recv {

           set req.backend = webs;

           return(pass); #测试的时候把默认配置的return(lookup)改为return(pass),否 则,后续的请求就直接去查找缓存了,看不出测试效果。

       }

 5、定义对后端进行健康状态的检测,需要在backend区段的上面,并在backend区段进行引用

       probe healthchk {

           .url = "/";

           .interval = 3s;

           .timeout = 10ms

           .window = 3;

           .threshold = 2;

           .initial = 3;

           .expected_response = 200;

       }

       backend web1 {

           .probe = healthchk;

       }

       backend web2 {

           .probe = hearlthchk;

       }

   6、定义动静分离,假定web1提供动态内容,web2提供静态内存,不过要先把director端注释掉

       sub vcl_recv {

           if (req.url ~ "(?i)\.php$") {

               set req.backend = web1;

           } else {

               set req.backend = web2;

           }

       }

       sub vcl_fetch {

           set beresp.http.From-Backend = beresp.backend.ip; #用于测试是否动静个来自对应的服务器

       }

7、定义反盗链功能

       sub vcl_recv {

           if (req.http.referer ~ "http://.*") {

           if ( !(req.http.referer ~ "http://.*\.google\.com" ||

                  req.http.referer ~ "http://.*\.baidu\.com" ||

                  req.http.referer ~ "http://.*\.myselfsite\.com"))

           {

               set req.http.host = "www.myselfsite.com";

               set req.url = "/login/login.html";

           }

       }

   }

8、如何知道缓存是否命中,以及命中的次数

       sub vcl_deliver {

           if (obj.hits > 0) {

               set resp.http.X-Varnish-Cache = "HIT";

               set resp.http.X-Cache-Hits = obj.hits;

           } else {

               set resp.http.X-Varnish-Cache = "MISS";

           }

       }

9、去掉对静态文件请求时所带的Cookie信息,可以提供缓存命中率

       sub vcl_recv {

           if (req.url ~ "(?i)\.(html|htm|jpg|gif|ico|jpeg|png|js|css|swf)(\?[a-z0-9]+)?$") {

               unset req.http.Cookie;

           }

       }

       sub vcl_fetch {

           if (req.url ~ "(?i)\.(html|htm|jpg|gif|ico|jpeg|png|js|css|swf)(\?[a-z0-9]+)?$") {

               unset beres.backend.set-cookie;

           }

       }

  10、手动清除过期的缓存

       acl purgers {

           "127.0.0.1";

           "192.168.0.0"/24;

       }

       sub vcl_recv {

           if (req.request == "PURGE") {

               if (!client.ip ~ purgers) {

                   error 405 "Method not allowed";

               }

               return (lookup);

           }

       }

       sub vcl_hit {

           if (req.request == "PURGE") {

               purge;

               error 200 "Purged";

           }

       }

       sub vcl_miss {

           if (req.request == "PURGE") {

               purge;

               error 404 "Not in cache";

           }

       }

       sub vcl_pass {

           if (req.request == "PURGE") {

               error 502 "PURGE on a passed object";

           }

       }