若是有对以下的配置命令有不明晰的,附件有在下翻译的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";
}
}