/ 中存储网

Varnish缓存服务器的安装与配置

2013-09-03 11:28:47 来源:ITJS.CN

介绍

Varnish是一款高性能的开源HTTP加速器,挪威最大的在线报纸Verdens Gang使用3台Varnish代替了原来的12台Squid,性能居然比以前更好。Varnish 的作者Poul-Henning Kamp是FreeBSD的内核开发者之一,他认为现在的计算机比起1975年已经复杂许多。在1975年时,储存媒介只有两种:内存与硬盘。但现在计算机系统的内存除了主存外,还包括了cpu内的L1、L2,甚至有L3快取。硬盘上也有自己的快取装置,因此Squid cache自行处理物件替换的架构不可能得知这些情况而做到最佳化,但操作系统可以得知这些情况,所以这部份的工作应该交给操作系统处理,这就是Varnish cache设计架构。目前很多互联网公司在使用Varnish,其中包括Facebook。

特性

VCL(Varnish Configuration Language):区别于其他系统,Varnish采用了自身的配置语言来配置,非常容易上手,这些配置会被编译成二进制机器码,明显加快了执行速度。

Health checks:完善的健康检查机制。

ESI(Edge Side Includes):在HTML中嵌入动态脚本文件。

Directors:后端服务器的调度方式:random,round-robin,client,hash,DNS。

Purging and banning:强大的缓存清除功能,可以以正则表达式的形式清除缓存。

Logging in Varnish:Varnish的log不是记录在文件中的,而是记录在共享内存中。当日志大小达到分配的共享内存容量,覆盖掉旧的日志。以这种方式记录日志比文件的形式要快很多,并且不需要磁盘空间。

丰富的管理程序:varnishadm,varnishtop,varnishhist,varnishstat以及varnishlog等。

环境

OS: CentOS 5.5

varnish: 2.1.5

安装

首先安装ncurses-devel,否则varnishstat,varnishtop都无法编译完成

$ yum install ncurses-devel

接下来安装varnish

$ wget http://repo.varnish-cache.org/source/varnish-2.1.5.tar.gz

$ tar -zxvf varnish-2.1.5.tar.gz

$ cd varnish-2.1.5

$ ./configure --prefix=/usr/local/varnish-2.1.5

$ make && make install

启动

$ /usr/local/varnish2.1.5/sbin/varnishd -f 

/usr/local/varnish2.1.5/etc/varnish/default.vcl 

-T 127.0.0.1:2000 -a 0.0.0.0:80 -s file,/tmp,200M

其中-f用来指定配置文件,-T指定管理台的访问地址,-a指定Varnish监听地址,-s指定Varnish以文件方式来缓存资源,地址为/tmp,大小200MB。

配置

#后端处理器b1

backend b1{

.host = "192.168.2.110";

.port = "81";

.connect_timeout = 5s;

.first_byte_timeout= 5s;

.probe = {

#health check

.url = "/check.txt";

.interval = 5s;

.timeout = 5s;

.window = 5;

.threshold = 3;

}

}

#后端处理器b2

backend b2{

.host = "192.168.2.109";

.port = "81";

.connect_timeout = 5s;

.first_byte_timeout = 5s;

.probe = {

#health check

.url = "/check.txt";

.interval = 5s;

.timeout = 5s;

.window = 5;

.threshold = 3;

}

}

#以轮询方式实现负载均衡

director d1 round-robin {

{

.backend = b1;

}

{

.backend = b2;

}

}

#acl

acl purge {

"localhost";

"192.168.0.64";

}

sub vcl_recv {

# 设置director

set req.backend = d1;

# 如果从后端返回的资源中含有Set-Cookie头的话,那么varnish不会进行缓存;

# 如果客户端发送了Cookie头的话,那么varnish会bypass(绕开)缓存,

# 直接发送到后端,并不会进行缓存,所以需要如下处理:

if ( !( req.url ~ ^/admin/) ) {

unset req.http.Cookie;

}

if (req.http.Cookie == "") {

remove req.http.Cookie;

}

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 != "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);

}

# allow PURGE from localhost and 192.168.0...

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

if (!client.ip ~ purge) {

error 405 "Not allowed.";

}

return (lookup);

}

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_hit {

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

# Note that setting ttl to 0 is magical.

# the object is zapped from cache.

set obj.ttl = 0s;

error 200 "Purged.";

} else {

return (deliver);

}

}

sub vcl_miss {

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

error 404 "Not in cache.";

} else {

return (fetch);

}

}

sub vcl_fetch {

#设置TTL为1个小时

set beresp.ttl = 1h;

if (!beresp.cacheable) {

return (pass);

}

if (beresp.http.Set-Cookie) {

return (pass);

}

return (deliver);

 }

sub vcl_deliver {

return (deliver);

}

启动脚本

$ wget -O varnishd https://raw.github.com/gist/3671408/3a51578bbd60a4cf8317bdc9508527b81eb23da5/varnishd

$ cp varnishd /etc/init.d/varnishd

$ chmod +x /etc/init.d/varnishd

$ /etc/init.d/varnishd start

Subroutine列表

vcl_recv 在请求开始时候被调用,在请求已经被接收到并且解析后调用。目的就是决定是否处理这个请求,怎么处理,使用哪个后端。vcl_recv以return结束,参数可以为如下关键字:

error code [reason]:返回错误码给客户端,丢弃请求。

pass:转换到pass模式。控制权最后会转移到vcl_pass。

pipe:转换到pipe模式。控制权最后会转移到vcl_pipe。

lookup:在缓存中寻找请求对象。控制权最后会转移到vcl_hit或者vcl_miss,决定于对象是否在缓存中。

vcl_pipe 当进入pipe模式的时候被调用。在这个模式中,请求会被转移到后端,后续的数据不管是从客户端还是后端来的都会以不变的方式传送,直到连接关闭为止。vcl_pipe以return结束,参数可以为如下关键字:

error code [reason]:返回错误码给客户端,丢弃请求。

pipe:以pipe模式执行。

vcl_pass 当进入pass模式的时候会被调用。在这个模式中,请求会被传送到后端,然后后端的响应会被传送回客户端,但是响应不会进入缓存中。接下来通过相同客户端连接发起的请求会以普通的方式来处理。vcl_pass以return结束,参数可以为如下关键字:

error code [reason]:返回错误码给客户端,丢弃请求。

pass:以pass模式执行。

restart:重新启动这个事务。增加了重启计数。如果重启的次数高于max_restarts,varnish会引起一个错误。

vcl_hash 你如果把想把数据加入到hash中,那么调用hash_data()。vcl_hash以return结束,参数可以为如下关键字:

hash:执行hash逻辑。

vcl_hit 如果请求的对象在缓存中被找到了,那么在缓存查找结束后被调用。vcl_hit以return结束,参数可以为如下关键字:

deliver:deliver缓存对象到客户端。控制权最后会转移到vcl_deliver。

error code [reason]:返回错误码给客户端,丢弃请求。

pass:切换到pass模式。控制权最后会转移到vcl_pass。

restart:重新启动这个事务。增加了重启计数。如果重启的次数高于max_restarts,varnish会引起一个错误。

vcl_miss 如果请求的对象在缓存中没有被找到,那么在缓存查找结束后被调用。目的是为了决定是否去后端获取这个请求对象,并且要选择哪个后端。vcl_miss以return结束,参数可以为如下关键字:

error code [reason]:返回错误码给客户端,丢弃请求。

pass:切换到pass模式。控制权最后会转移到vcl_pass。

fetch:去后端获取请求对象。控制权最后会转移到vcl_fetch。

vcl_fetch 当一个对象被成功从后端获取的时候此方法会被调用。vcl_fetch以return结束,参数可以为如下关键字:

deliver:可能把对象放入缓存中,然后再deliver到客户端。控制权最后会转移到vcl_deliver。

error code [reason]:返回错误码给客户端,丢弃请求。

esi:以ESI形式来处理刚刚被获取到的对象。

pass:切换到pass模式。控制权最后会转移到vcl_pass。

restart:重新启动这个事务。增加了重启计数。如果重启的次数高于max_restarts,varnish会引起一个错误。

vcl_deliver当一个缓存的对象被deliver到客户端的时候,此方法会被调用。vcl_deliver以return结束,参数可以为如下关键字:

deliver:发送对象到客户端。

error code [reason]:返回错误码给客户端,丢弃请求。

restart:重新启动这个事务,增加重启计数。如果重启的次数高于max_restarts,varnish会引起一个错误。