码迷,mamicode.com
首页 > 其他好文 > 详细

varnish及其应用(三)

时间:2015-06-07 21:41:37      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:varnish

4、fetch子进程

如果收到的后端响应报文的ttl值小于0(失效了),或者响应报文中有Set-cookie首部,或者首部Vary等于“*”,则设定响应报文的ttl值为120秒,返回关键字hit_for_pass进行处理

sub vcl_fetch {
     if (beresp.ttl <= 0s ||
         beresp.http.Set-Cookie ||
         beresp.http.Vary == "*") {
               /*
                * Mark as "Hit-For-Pass" for the next 2 minutes
                */
               set beresp.ttl = 120 s;
               return (hit_for_pass);
     }
     return (deliver);
 }



5移除单个缓存对象:


purge与GET、DEAD一样,也是一种请求类型,用于清理缓存中的某特定对象及其变种(variants),因此,在有着明确要修剪的缓存对象时可以使用此种方式。HTTP协议的PURGE方法可以实现purge功能,不过,其仅能用于vcl_hit和vcl_miss中,它会释放内存工作并移除指定缓存对象的所有Vary:-变种,并等待下一个针对此内容的客户端请求到达时刷新此内容。另外,其一般要与return(restart)一起使用。下面是个在VCL中配置的示例:

先定义一个acl (access control list),将可以做purge的ip地址列入该名单,注意限定网络的方法;

在vcl_recv中添加条件判断:不在白名单中的用户使用了purge则返回错误代码并丢弃该请求,这可以;

如果用户是允许purge的用户,且缓冲中有查找的内容,则在vcl_hit中做条件判断——如果是purge方法,则做相应的移除操作,并返回状态码200及原因说明“Purged”;

如果用户是允许purge的用户,且缓冲中没有缓冲内容,则在vcl_miss引擎中做条件判断——如果是purge方法,则调用purge动作,并返回状态码404及原因说明“没有相应的缓存”;

如果用户是允许purge的用户,但传送到pass引擎了,则返回错误代码502及说明“在错误的对象上使用了purge方法”。

这时要注意是否开启了vcl_recv子进程中关于req.request的设置,如果开启了,则需在vcl_recv子进程里添加进允许purege能被引用到hit或miss引擎的机制。

acl purgers {
"127.0.0.1";
"172.16.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";
}
}

技术分享

技术分享



最终的配置如下:

[root@aunt-s ~]# grep -v "^[[:space:]]*#" /etc/varnish/default.vcl
backend default {
  .host = "172.16.20.150";
  .port = "80";
}
acl purgers {
"127.0.0.1";
"172.16.0.0"/16;
}
 sub vcl_recv {
     if (req.restarts == 0) {
 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;
 }
     }
     if (req.request == "PURGE") {
if ( !client.ip ~ purgers ) {
   error 405 "Method not allowed.";
}
     }
     if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "PUT" &&
       req.request != "POST" &&
       req.request != "TRACE" &&
       req.request != "OPTIONS" &&
       req.request != "DELETE" &&
req.request != "PURGE" ) {
         /* Non-RFC2616 or CONNECT which is weird. */
         return (pipe);
     }
     if (req.request != "GET" && req.request != "HEAD" && req.request != "PURGE") {
         /* We only deal with GET and HEAD by default */
         return (pass);
     }
     if (req.http.Authorization || req.http.Cookie) {
         /* Not cacheable by default */
         return (pass);
     }
     return (lookup);
 }
 sub vcl_pass {
    if (req.request == "PURGE") {
error 502 "Purge on a pass object.";
    }
     return (pass);
 }
 sub vcl_hit {
    if (req.request == "PURGE") {
purge;
error 200 "Pureged.";
    }
     return (deliver);
 }
 sub vcl_miss {
    if (req.request == "PURGE") {
purge;
error 404 "Not in cache.";
    }
     return (fetch);
 }
 sub vcl_deliver {
if (obj.hits>0) {
   set resp.http.X-Cache = "HIT";
} else {
   set resp.http.X-Cache = "MISS";
}
     return (deliver);
 }



6、定义要使用的后端主机


(1)backend{} 定义单个后端主机

方法:先用backend NAME{}定义一个后端主机,一个后端主机定义一个backend,有多个后端就用多个backend定义,然后在需要相关的引擎里的合适位置用if条件判断引用对应的后端主机。

① node2上配置好php服务:

[root@node2 ~]# yum install -y php
……
Installed:
  php.x86_64 0:5.3.3-38.el6                                                                                               
Dependency Installed:
  php-cli.x86_64 0:5.3.3-38.el6                              php-common.x86_64 0:5.3.3-38.el6                             
Complete!
[root@node2 ~]# vim /var/www/html/index.php
<h1>test page on node2</h1>
<?php
phpinfo();
?>


node1后端主机仍只提供静态页面html服务

② 在varnish缓存策略配置文件中定义后台主机:

backend default {
  .host = "172.16.20.150";
  .port = "80";
}
backend static {
  .host = "172.16.20.150";
  .port = "80";
}
backend appsrv {
  .host = "172.16.20.200";
  .port = "80";
}


上面使用了2个主机,但定义了三个后端,其中一个是动态页面服务后端,一个静态页面服务后端,还有一个是需要作出后端主机选择而又没有指定时的默认后端(default)。


③ 在varnish缓存策略配置文件中定义什么时候调用后端主机:

一般是在vcl.recv子进程中第一个做出return()或者error的if条件判断语句之前定义即可。

在sub vcl_recv {}中添加如下行,位置如上说明:

sub vcl_recv {
 if (req.url ~ "\.php$") {
            set req.backend = appsrv;
     } else {
            set req.backend = static;
     }
}


④ 使用验证:

[root@aunt-s ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load v1 default.vcl
200        
VCL compiled.
varnish> vcl.use v1
200        
varnish>

技术分享


上图右上角的图片是静态页面,动静分离后将该图片对应的地址的调用地址分配到statis主机(node1)上了,但node1上是没有这个图片的,所以没有显示。

实际应用中将页面的动态内容和静态内容分离后,需要做好动态页面上的静态内容的绝对路径重写到静态服务器上。

(2)director{} 定义后端主机逻辑组

Varnish中可以使用director{}指令将一个或多个近似的后端主机定义为一个逻辑组,以逻辑组作为一个整体接受同一种动作或者提供同一种服务。不同的director可以使用同一个后端主机,而某director也可以使用“匿名”后端主机(在director中直接进行定义)。每个director都必须有其专用名,且在定义后必须在VCL中进行调用,VCL中任何可以指定后端主机的位置均可以按需将其替换为调用某已定义的director。

调用方法:

在vcl_recv上,一般用

set req.backend = DIRECTOR


在逻辑组内可以指定调度方式(也叫挑选方法)来轮流将请求发送至这些主机上。Varnish的director支持的挑选方法中比较简单的有round-robin和random两种。其中,round-robin类型没有任何参数,只需要为其指定各后端主机即可,挑选方式为“轮叫”,并在某后端主机故障时不再将其视作挑选对象;random方法随机从可用后端主机中进行挑选,每一个后端主机都需要一个.weight参数以指定其权重(仅能用于random模式必须使用.weight;round-robin必不能用.retries和.weight)。

Varnish 2.1.0后,random挑选方法又多了两种变化形式client和hash。client类型的director使用client.identity作为挑选因子,这意味着client.identity相同的请求都将被发送至同一个后端主机。client.identity默认为client.ip,但也可以在VCL中将其修改为所需要的标识符。类似地,hash类型的director使用hash数据作为挑选因子,这意味着对同一个URL的请求将被发往同一个后端主机,其常用于多级缓存的场景中。然而,无论是client还hash,当其倾向于使用后端主机不可用时将会重新挑选新的后端其机。

同时还可以director级别使用.retries参数来设定查找一个健康后端主机时的尝试次数。

另外还有一种称作fallback的director,用于定义备用服务器,如下所示:


director b3 fallback {

  { .backend = www1; }

  { .backend = www2; } // will only be used if www1 is unhealthy.

  { .backend = www3; } // will only be used if both www1 and www2

                       // are unhealthy.

}


实操:

[root@aunt-s ~]# vim  /etc/varnish/default.vcl
probe healthchk {
   .url = "/index.html";
   .window = 5;
   .threshold = 3;
   .interval = 3s;
   .timeout = 1s;
   .initial = 3;
   .expected_response = 200;
}
backend default {
  .host = "172.16.20.150";
  .port = "80";
  .probe = healthchk;
}
backend appsrv {
  .host = "172.16.20.200";
  .port = "80";
  .probe = {
        .url = "/index.php";
        .window = 5;
        .threshold = 3;
        .interval = 3s;
        .timeout = 1s;
        .expected_response  = 200;
  }
}
director mystaticsrv round-robin {
#   .retries = 3;
   {
        .backend = appsrv;
#        .weight = 1;
   }
   {
        .backend = {
        .host = "172.16.20.150";
        .port = "80";
        }
#        .weight = 2;
   }
}
acl purgers {
        "127.0.0.1";
        "172.16.0.0"/16;
}
 sub vcl_recv {
   ……
   
     if (req.url ~ "/index.html") {
        return(pass);
     }
     if (req.url ~ "\.php$") {
            set req.backend = appsrv;
     } else {
            set req.backend = mystaticsrv;
     }
……


[root@aunt-s ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load v7 default.vcl
200        
VCL compiled.
varnish> vcl.use v7
200



如上示例中,web1为显式定义的后端主机,而webservers这个directors还包含了一个“匿名”后端主机(backweb2.magedu.com)。webservers从这两个后端主机中挑选一个主机的方法为round-robin。


但是,此设置无论怎么刷新,都只能定位到一个后端服务器上,修改为random模式后还是只能定位到一个主机上。

解决办法:调整sub vcl_recv代码如下

 

sub vcl_recv {
   ……
   
     if (req.url ~ "\.php$") {
            set req.backend = appsrv;
     } else {
            set req.backend = mystaticsrv;
     if (req.url ~ "/index.html") {
        return(pass);
     }
     }
……


技术分享




7、后端服务器健康状态监测


Varnish可以检测后端主机的健康状态,在判定后端主机失效时能自动将其从可用后端主机列表中移除,而一旦其重新变得可用还可以自动将其设定为可用。为了避免误判,Varnish在探测后端主机的健康状态发生转变时(比如某次探测时某后端主机突然成为不可用状态),通常需要连续执行几次探测均为新状态才将其标记为转换后的状态。


每个后端服务器当前探测的健康状态探测方法通过.probe{}进行设定,其结果可由req.backend.healthy变量获取,也可通过varnishlog中的Backend_health查看或varnishadm的debug.health查看。


定义方式有两种:

方法一:先定义.probe{}检测方法,然后在 设定主机backend{}或者director{}时调用;

方法二:直接在设定主机backend{}时定义该主机的检测方法

在配置文件中按如下设置,其他设置不变:

[root@aunt-s ~]# vim  /etc/varnish/default.vcl
probe healthchk {
   .url = "/index.html";
   .window = 5;
   .threshold = 3;
   .interval = 3s;
   .timeout = 1s;
   .initial = 3;
   .expected_response = 200;
}
backend default {
  .host = "172.16.20.150";
  .port = "80";
  .probe = healthchk;
}
backend static {
  .host = "172.16.20.150";
  .port = "80";
  .probe = healthchk;
}
backend appsrv {
  .host = "172.16.20.200";
  .port = "80";
  .probe = {
        .url = "/index.php";
        .window = 5;
        .threshold = 3;
        .interval = 3s;
        .timeout = 1s;
        .expected_response  = 200;
  }
}



[root@aunt-s ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> vcl.load v2 default.vcl
200        
VCL compiled.
varnish> vcl.use v2
200        
varnish> backend.list
200        
Backend name                   Refs   Admin      Probe
default(172.16.20.150,,80)     3      probe      Healthy 5/5
static(172.16.20.150,,80)      2      probe      Healthy 5/5
appsrv(172.16.20.200,,80)      2      probe      Healthy 5/5



同时在后端服务器上可以看到健康检测的日志记录


[root@node2 ~]# tail -3 /var/log/httpd/access_log
172.16.20.100 - - [07/Jun/2015:11:41:36 +0800] "GET /index.php HTTP/1.1" 200 43293 "-" "-"
172.16.20.100 - - [07/Jun/2015:11:41:39 +0800] "GET /index.php HTTP/1.1" 200 43293 "-" "-"
172.16.20.100 - - [07/Jun/2015:11:41:42 +0800] "GET /index.php HTTP/1.1" 200 43293 "-" "-"



必要时应该在后端主机上关闭健康检测的日志记录。


将主页换名,查看检测是否正常工作:

[root@node2 ~]# mv /var/www/html/index.php /var/www/html/index.php.bak


技术分享


[root@node2 ~]# mv /var/www/html/index.php.bak /var/www/html/index.php


技术分享




8、案例说明:

# Drop any cookies sent to Wordpress.

sub vcl_recv {

if (!(req.url ~ "wp-(login|admin)")) {

unset req.http.cookie;

}

}

说明:当请求报文中没匹配到 "wp-login"或 "wp-admin"(即登录或管理时发的请求报文)时,撤销请求报文首部中的cookie信息。

意义:用户登录后与服务器建立连接,派发cookie后,每次发过来的请求报文都有cookie信息,而一般情况下,含cookie首部的报文是不缓存的,这样大大影响响应速率增加后端服务器的压力,撤销cookie首部后就能缓存报文body了。

sub vcl_recv {

 if (req.http.host ~ "(?i)^(www.)?doco.com$") {

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

   set req.backend = www;

 } elsif (req.http.host ~ "(?i)^images.doco.com$") {

   set req.backend = images;

 } else {

   error 404 "Unknown virtual host";

 }

}

说明:如果发送请求报文首部中指定的服务器主机名为“www.doco.com”或“doco.com”(忽略大小写),则设定req.http.host的值为 “www.doco.com” ,同时设定名为www服务器作为相应的后端服务器;

如果发送请求报文首部中指定的服务器主机名为 "images.doco.com"(忽略大小写),则设定后端服务器为images服务器;

其他请求报文中服务器主机名为其他情况时,返回错误结果,响应码404,原因说明“未知的虚拟主机”








参考:

https://www.varnish-cache.org/docs/3.0/reference/vcl.html#varnish-configuration-language


http://baike.baidu.com/link?url=fYBhU6x-FvtcasMLTvT-J3EgSwnf6XKmHu1vw0FAxB73__BpSDdg6G72qKn5gxBzQsfvNADwoPfymuEgS8Ssva





抽风


varnish及其应用(三)

标签:varnish

原文地址:http://ctrry.blog.51cto.com/9990018/1659477

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!