用Varnish加速动态页面-对PHP/Drupal的页面缓存

浏览:168

varnish的基本介绍就不在此赘述,关于使用varnish缓存,之前也有几篇文件进行介绍,不过大部分情况下,我们使用varnish限于两个方面,其一是用varnish做反向代理,另一个用途就是用它来缓存静态内容,比如图片、css、js文件等。既然varnish可以缓存任何http请求,那么本文就varnish关于动态页面的缓存做一些测试和应用,文中举例基于drupal系统,也可以应用基于PHP的其他系统。


对于Varnish的基本概念,请参考之前的两篇文章:
高负载网站之Varnish与Drupal – 基本篇
Varnish构建高负载Drupal网站 – 高级篇

首先了解几个概念,


1. Varnish不缓存带有Set-Cookie头的http输出。
2. 对于HTTP协议中缓存部分,Varnish遵从http协议部分。如:带有如下头信息,Control-Cache: no-store, no-cache, must-revalidate, post-check=0, pre-check=0,默认varnish不会缓存。
3. HTTP协议中缓存部分,Control-Cache优先于Expires,Pragma: no-cache 是HTTP1.0的产物,可以不考虑。



Varnish缓存操作,一般有两个方法,
1. 在varnish的配置文件设置。
2. 通过http协议指定,比如Control-Cache。


第一种方法耦合性较低,只需修改vcl即可,但是灵活性较差,如果要独立设置每个页面的ttl可能比较麻烦。
第二种方法较为灵活,可以设置每一个页面的缓存时间,比如Control-Cache: max-age=10. (缓存10秒),缺点就是耦合性,既要在PHP端设置,又要在Varnish里面设置。


小插曲:如果使用Control-Cache: max-age=10这种方式缓存的话,varnish可以缓存,但是会出现一个问题,客户端的浏览器同样会缓存,如果不让客户端浏览器缓存,而只让varnish缓存,可以使用 Control-Cache: max-age=0; s-maxage:10.



这里,我们选择使用VCL,也就是上面所说的第一种方法来缓存http动态页面。
如下假设:
a) 要缓存的页面url为 /abc/* 的形式,
b) 只缓存匿名用户的页面(登录用户以后再介绍)
c) 登录用户需要有一个独有的cookie,如DRUPAL_UID=11


1. 在vcl_recv里面添加如下代码(此处,一定要将登录用户的请求pass到后端服务器,否则,也会得到缓存页面,因为varnish的hash默认没有cookie,所以登录用户同样会命中匿名用户的缓存数据)。





 if (req.request == "GET" && req.url ~ "^/abc/.*"){
    if (req.http.Cookie ~ "DRUPAL_UID=[1-9][0-9]*"){
      return (pass);
    } 
    else{
      remove req.http.Cookie;
      return (lookup);
    }
 }

2. 在vcl_fetch里面添加如下代码





if(req.request == "GET" && req.http.Cookie !~ "DRUPAL_UID=[1-9][0-9]*" && req.url ~ "^/abc/.*"){
   unset beresp.http.Pragma;
   unset beresp.http.Expires;
   unset beresp.http.set-cookie;
   set beresp.ttl = 2h; 
   #time to liveset beresp.do_gzip = true;
   set beresp.grace = 20m; 
   #grace timereturn (deliver);
}

在vcl_fetch里面注意,最好把set-cookie unset掉,这样就不会修改客户端的cookie了(一般情况,varnish向后台用户发送的是匿名请求,这样set-cookie肯定是一个匿名的session信息,如果当前用户是登录用户,就会导致当前用户logout,这点特别注意)。


这样,就在varnish里面强制缓存了所有/abc/开始的页面内容,缓存时间为2小时。


最后补充一个vcl的调试技巧,在varnish3.x里面引入了std模块,varnish vmod_std包含了一些常用函数,所以调试vcl的时候,我们可以使用std.syslog(1, xxx)等语句,将某个变量记录到syslog里面(/var/log/messages),方便观察结果。


在Varnish的设置中,理解其处理http请求的过程非常重要,因此,这里贴一张VCL的流程图,以便更好的理解varnish处理的过程。


varnish flow

varnish 处理http的流程



后记:关于登录用户页面的缓存,下一篇再做讨论。Varnish的负载均衡配置,可以参考这篇文章《Varnish前端代理Drupal的配置以及Jenkins》。


top