- Varnish简介
Varnish是高性能且开源的反向代理服务器和HTTP加速器(cache server)。其开发者Poul-Henning Kamp是FreeBSD核心的开发人员之一。Varnish采用全新的软件体系结构,和现在的硬件体系配合比较紧密。
当前计算机系统的内存除了主存外,还包括CPU的L1级缓存、L2级缓存,甚至还包括L3级缓存。硬盘也有缓存,而Squid的架构导致其无法做到最佳存取,但操作系统可以实现这部分功能,所以这部分工作应该交给操作系统来处理,这就是Varnish Cache设计架构。挪威最大的在线报纸Verdens Gang(vg.no)使用了3台Varnish服务器代替了原来的12台Squid服务器,而且性能比以前更好,这是Varnish最成功的应用案例之一。目前,Varnish可以在FreeBSD6.0/7.0、Solaris和Linux 2.6内核上运行。
- Varnish的结构特点
Varnish把数据存放在服务器的内存中,这种模式的效率是最高的,不过重启后数据会消失,官方透露3.0版本可以解决这个问题。Varnish可以设置0~60秒的精确缓存时间,不过32位的机器支持的缓存文件最大为2 GB。Varnish采用VCL的配置,而且具有强大的管理功能,如top、stat、admin、lis,所以管理方式比较灵活。Varnish的状态机设计不仅巧妙,结构也很清晰,利用二叉堆管理缓存文件,即可达到随时删除的目的。
与传统的Squid比较相比
Varnish具有性能更高、速度更快、管理更加方便等诸多优点:
Varnish采用了“Visual Page Cache”技术,所有缓存的数据都直接从内存读取,而Squid从硬盘读取缓存的数据,它避免了Squid频繁在内存、磁盘中交换文件,性能要比Squid高。
Varnish稳定性比Squid高,宕机率很低。
通过Varnish管理端口,可以使用正则表达式快速、批量地清除部分缓存,这一点是Squid不能具备的。
Varnish可以支持更多的并发连接。因为Varnish的TCP连接与释放比Squid快,所以在高并发连接情况下可以支持更多的TCP连接。
不足:Varnish在高并发状态下,CPU、I/O和内存等资源的开销高于Squid。Varnish的进程一旦挂起、崩溃或者重启,缓存的数据都会从内存中释放出来。此时的所有请求都会被发送到后端应用服务器上,在高并发的情况下,就会给后端服务器造成很大压力。
- Varnish工作原理
大致过程:
当大量的请求访问到达一台服务器后,容易造成服务器宕机,在服务器前加一台(批)缓存机器,将大量请求分散到各个缓存机器上,就能大大减少服务器工作量.
简而言之,varnish会将服务器中的一部分内容缓存到自己的缓存空间中,客户对服务器的访问会先到达varnish服务器,当varnish里有客户需要的东西,就直接给予回应,如果没有,varnish会向服务器请求这部分内容,缓存在自己身上,从而减少后台的访问量.
流程如下:
Varnish配置调整,需要了解Varnish的配置语法,也就是VCL语言。下面对VCL常用的一些函数和变量进行介绍。
(1)vcl_recv模块
用于接收和处理请求。当请求成功被调用后,Varnish通过判断请求的数据来决定如何处理请求。此模块一般以如下几个关键字结束。
pass:表示进入pass模式,把请求交给vcl_pass模块处理。
pipe:表示进入pipe模式,把请求交给vcl_pipe模块处理。
error code [reason]:表示把错误标识返回给客户端,并放弃处理该请求。错误标识包括200、405等。“reason”是对错误的提示信息。
(2)Roulette ist ein sehr geselliges Spiel, alle halten gleicherma?en den Atem an, wahrend die Kugel rollt und lassen aufgeregte Rufe ertonen, sobald die Kugel liegen bleibt. New Roman;”>vcl_pipe模块
此模块在请求进入pipe模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,也就是在当前连接未关闭时,服务器将不变的内容返回给客户端,直到该连接被关闭。
(3)vcl_pass模块
此模块表示当请求被pass后,用于将请求直接传递至后端应用服务器。后端应用服务器在接收请求后将数据发送给客户端,但不进行任何数据的缓存,在当前连接下每次都返回最新的内容。
(4)lookup
一个请求在vcl_recv中被lookup后,Varnish将在缓存中提取数据。如果缓存中有相应的数据,就把控制权交给vcl_hit模块;如果缓存中没有相应的数据,请求将被设置为pass并将其交给vcl_miss模块。
(5)vcl_hit模块
执行lookup指令后,Varnish在缓存中找到请求的内容后将自动调用该模块。
在此模块中,deliver表示将找到的数据发送给客户端,并把控制权交给vcl_deliver模块。
(6)vcl_miss模块
执行lookup后,Varnish在缓存中没有找到请求的内容时会自动调用该方法。此模块可以用于判断是否需要从后端服务器获取内容。
在此模块中,fetch表示从后端获取请求的数据,并把控制权交给vcl_fetch模块。
(7)vcl_fetch模块
在后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端。
(8)vcl_deliver模块
当一个没有被缓存的数据交付给客户端的时候被调用。
(9)vcl_timeout 模块
在缓存数据到期前调用此模块。
在此模块中,discard表示从缓存中清除到期数据。
(10)vcl_discard模块
在缓存数据到期后或缓存空间不够时,自动调用该模块。
在此模块中keep表示将数据继续保留在缓存中。
环境:rhel6.5
主机及软件:
server3 192.168.25.3 varnish
server4 192.168.25.4 apache 要做虚拟主机
server5 192.168.25.5 apache
varnish软件包:
varnish-3.0.5-1.el6.x86_64.rpm
varnish-libs-3.0.5-1.el6.x86_64.rpm
server3上的配置
[root@server3 ~]# ls
Desktop Pictures varnish varnish-libs-3.0.5-1.el6.x86_64.rpm
Documents Public varnish-3.0.4-1.el6.x86_64.rpm Videos
Downloads rhel6 varnish.pdf varnish-3.0.5-1.el6.x86_64.rpm
Music Templates varnish-libs-3.0.4-1.el6.x86_64.rpm
[root@server3 ~]# rpm -ivh varnish-3.0.5-1.el6.x86_64.rpm
Preparing… ########################################### [100%]
package varnish-3.0.5-1.el6.x86_64 is already installed
[root@server3 ~]# rpm -ivh varnish-libs-3.0.5-1.el6.x86_64.rpm
Preparing… ########################################### [100%]
package varnish-libs-3.0.5-1.el6.x86_64 is already installed
配置varnish服务端口
[root@server3 ~]# vim /etc/sysconfig/varnish
VARNISH_LISTEN_PORT=80
#配置一个后端服务器
7 backend web {
8 .host = "192.168.25.3";
9 .port = "80";
10 }
11
12 #查看缓存命中情况
13 sub vcl_deliver {
14 if (obj.hits > 0) {
15 set resp.http.X-Cache = "HIT from web^C cache";
16 }
17 else {
18 set resp.http.X-Cache = "MISS from web cache";
19 }
20 return (deliver);
21 }
22
[root@server3 ~]# service varnish reload
Loading vcl from /etc/varnish/default.vcl
Current running config name is reload_2017-09-17T12:13:36
Using new config name reload_2017-09-17T12:22:01
VCL compiled.
available 0 boot
available 0 reload_2017-09-17T12:05:20
available 4 reload_2017-09-17T12:13:36
active 0 reload_2017-09-17T12:22:01
Done
测试缓存命中情况: curl -I 192.168.25.4(5)【两台apache主机】
###通过 varnishadm 手动清除缓存
# varnishadm ban.url .*$ #清除所有
# varnishadm ban.url /index.html #清除index.html页面缓存
# varnishadm ban.url /admin/$ #清除admin目录缓存
负载均衡:
23 #定义负载均衡
24
25 #定义多个不同域名站点的后端服务器
26
27 director lb round-robin { #把多个后端聚合为一个组
28 { .backend = web1; }
29 { .backend = web2; }
30 }
31
32
33 backend web1 {
34 .host = "192.168.25.4";
35 .port = "80";
36 }
37 backend web2 {
38 .host = "192.168.25.5";
39 .port = "80";
40 }
41 #当访问www.peter.com域名时从web1上取数据,访问bbs.peter.com域名时到web2取数据
42 #访问其他页面报错。
43
44 sub vcl_recv {
45 if (req.http.host ~ "^(www.)?peter.com") {
46 set req.http.host = "www.peter.com";
47 set req.backend = lb;
48 } elsif (req.http.host ~ "^bbs.peter.com") {
49 set req.backend = web2;
50 } else {
51 error 404 "peter cache";
52 }
53 }
54
55
56 #定义健康检查
57
58 probe healthcheck {
59 .url = "/index.html"; #哪个 url需要varnish请求
60 .interval = 5s; #检查的间隔时间
61 .timeout = 1s; #等待多长时间探针超时
62 .window = 5; #维持5个sliding window的结果
63 .threshold = 3; #至少有三次window是成功的,就宣告bachend健康
64 }
65
66 backend web1 {
67 .host = "192.168.25.4";
68 .port = "80";
69 .probe = healthcheck;
70 }
71 backend web2 {
72 .host = "192.168.25.5";
73 .port = "80";
74 .probe = healthcheck;
75 }
76
77
78 sub vcl_recv {
79 if (req.http.host ~ "^(www.)?peter.com") {
80 set req.http.host = "www.peter.com";
81 set req.backend = lb;
82 return (pass); #为了测试方便,不进行缓存。
83 } elsif (req.http.host ~ "^bbs.peter.com") {
84 set req.backend = web2;
85 } else {
86 error 404 "peter cache";
87 }
88 }
89
[root@server3 ~]# service varnish reload
varnish cdn推送平台
#需要安装php支持
# unzip bansys.zip -d /var/www/html
# vi /var/www/html/bansys/config.php #只保留如下设置,其余注释掉
<?php
$var_group1 = array(
'host' => array('192.168.25.3'),
'port' => '6082',
);
//varnish群组定义
//对主机列表进行绑定
$VAR_CLUSTER = array(
'www.peter.com' => $var_group1,
);
//varnish版本
//2.x和3.x推送命令不一样
$VAR_VERSION = "3";
?>
#bansys有两种工作模式,分别是:telnet和http模式。
#telnet模式需要关闭varnish服务管理端口的验证,注释掉/etc/sysconfig/varnish文件中的“-S $
{VARNISH_SECRET_FILE}”这行,重启varnish服务即可。
#如果是http模式需要对varnish做以下设置:
# vi /etc/varnish/default.vcl
acl westos {
#设置访问控制
"127.0.0.1";
"192.168.0.0"/24;
}
sub vcl_recv {
if (req.request == "BAN") {
if (!client.ip ~ westos) {
error 405 "Not allowed.";
}
ban("req.url ~ " + req.url);
error 200 "ban added";
}
}
# service varnish reload
推送:在浏览器中输入192.168.25.3:6082