一、前言
首先来简单认识一下什么是varnish?它能实现什么样的功能?.......
Varnish是一款高性能的开源HTTP加速器,常见的缓存服务开源解决方案有varnish、nginx、squid 、ats等,Varnish 的作者Poul-Henning Kamp是FreeBSD的内核开发者之一,varnish项目是2006年发布的第一个版本0.9.距今已经有十年了,此文档之前也提过varnish还不稳定,那是2007年时候编写的,经过varnish开发团队和网友们的辛苦耕耘,现在的varnish已经很健壮。很多门户网站已经部署了varnish,并且反应都很好,甚至反应比squid还稳定,且效率更高,资源占用更少。挪威最大的在线报纸 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好。相信在反向代理,web加速方面,varnish已经有足够能力代替squid。
二、varnish有哪些特性
1、Varnish的稳定性很高,两者在完成相同负荷的工作时,Squid服务器发生故障的几率要高于Varnish,因为使用Squid要经常重启;
2、Varnish访问速度更快,因为采用了“Page Cache”技术,所有缓存数据都直接从内存读取(映射),而squid是从硬盘读取,因而Varnish在访问速度方面会更快;
3、Varnish可以支持更多的并发连接,因为Varnish的TCP连接释放要比Squid快,因而在高并发连接情况下可以支持更多TCP连接;
4、Varnish可以通过管理端口,使用正则表达式批量的清除部分缓存,而Squid是做不到的;
5、squid属于是单进程使用单核CPU,但Varnish是通过fork形式打开多进程来做处理,所以可以合理的使用所有核来处理相应的请求。
三、Varnish的安装方式
Varnish的安装非常简单,常用的两种方式有yum安装和源码包安装,下面一源码安装来简单介绍:
1、安装前的准备
获取varnish软件
Varnish的官方站点为http://varnish-cache.org,这里面有varnish的最新说明文档,以及版本升级记录,从此站点可以找到varnish在SourceForge的下载链接,目前,varnish的最新版本是Varnish 2.1.2,下载完成后的包名为varnish-2.1.2.tar.gz,此处我们就以此版本为例,进行安装配置。
2、建立varnish用户以及用户组,并且创建Varnish缓存目录和日志目录:
[root@varnish-server ~]#useradd -s /sbin/nologin varnish
[root@varnish-server ~]#mkdir /data/varnish/cache
[root@varnish-server ~]#mkdir /data/varnish/log
[root@varnish-server ~]#chown -R varnish:varnish /data/varnish/cache
[root@varnish-server ~]#chown -R varnish:varnish /data/varnish/log
3、安装varnish(在此之前最好安装yum包组和pcre-devel、openssl-devel,否则编译时易出错)
这里我们将varnish安装编译到/usr/local/目录下,操作如下:
[root@varnish-server ~]#tar -zxvf varnish-2.1.2.tar.gz
[root@varnish-server ~]#cd varnish-2.1.2
[root@varnish-server ~]#./configure --prefix=/usr/local/varnish \
>--enable-dependency-trackin
>--enable-debugging-symbols
>--enable-developer-warnings
[root@varnish-server ~]#make
[root@varnish-server ~]#make install
至此,varnish安装完毕。
四、配置Varnish
VCL使用说明
VCL,即为Varnish Configuation Language,用来定义varnish的存取策略,VCL语法比较简单,跟C和perl比较相似,可以使用指定运算符“=”,比较运算符“==”,逻辑运算符“!,&&,!!”等形式。还支持正则表达样和用“~”进行ACL匹配运算,同时还可以使用“set”这样的关键字来指定变量。
需要注意的是,“\”字符在VCL里没有特别的含义,这点与其它语言略有不同,另外,VCL只是配置,并不是真正的编程语言,没有循环,也没有自定义变量。
在讲述Varnish配置之前,首先需要了解下varnish的配置语法,即VCL,下面对VCL常用的一些内置函数和公用变量进行详细介绍。
五、VCL状态
1、VCL有多个状态引擎,状态之间存在相关性,但状态引擎彼此间互相隔离;每个状态引擎可使用return(x)指明关联至哪个下一级引擎;每个状态引擎对应于vcl文件中的一个配置段
vcl_recv:接受用户请求进varnish的入口的引擎,接受到结果之后,利用return(lookup),将请求转交给vcl_hash引擎进行处理
vcl_hash:接受到用户请求后,对用户请求的URL进行hash计算,根据请求的首部信息,以及hash结果进行下一步处理的引擎
vcl_hit:经过vcl_hash引擎处理后,发现用户请求的资源本地有缓存,则vcl_hash引擎通过return(hit)将请求交给vcl_hit引擎进行处理,vcl_hit引擎处理后将请求交给vcl_deliver引擎,vcl_deliver引擎构建响应报文,响应给用户
vcl_miss:经过vcl_hash引擎处理后,发现用户请求的资源本地没有缓存,则vcl_hash引擎通过return(miss)将请求交给vcl_miss引擎进行处理
vcl_purge:经过vcl_hash引擎处理后,发现请求是对缓存的内容进行修剪时,则通过return(purge)交给vcl_purge引擎进行处理,vcl_purge引擎处理后,利用vcl_synth引擎将处理的结果告知给用户
vcl_pipe:经过vcl_hash引擎处理后,发现用户请求的报文varnish无法理解,则通过return(pipe),将请求交给vcl_pipe引擎,pipe引擎直接将请求交给后端真实服务器
vcl_pass:当请求经过vcl_hash处理后,发现请求报文不让从缓存中进行响应或其他原因没办法查询缓存,则由return(pass)或return(hit-for-pass)交由vcl_pass引擎进行处理
vcl_backend_fetch:当发现缓存未命中或由vcl_pass传递过来的某些不能查询缓存的请求,交由vcl_backend_fetch引擎处理,vcl_backend_fetch引擎会向后端真实web服务器发送请求报文,请求对应的资源
vcl_backend_response:当后端发送响应报文到varnish后,会由vcl_backend_resonse引擎进行处理,如:判断响应的内容是否可缓存,如果能缓存,则缓存下来后,交给vcl_deliver引擎,如果不能缓存,则直接交给vcl_deliver引擎,vcl_deliver引擎构建响应报文给客户端
varnish4.0版本的两个特殊的引擎
vcl_init:在处理任何请求之前要执行的vcl的代码,主要用于初始化VMOD,可用在后端主机有多台时,借助此引擎完成多台主机的负载均衡效果
vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMOD
2、VCL处理流程图
通过上面对VCL的介绍,读者对各个函数实现的功能已经有了一个了解,其实每个函数之间都是相互关联的,下图列出了varnish处理HTTP请求的一个运行流程图。
650) this.width=650;" src="https://s5.51cto.com/oss/201711/14/0d6b36c4807af2aa5e90bf0df1347236.png" title="1.PNG" alt="0d6b36c4807af2aa5e90bf0df1347236.png" />
VCL处理流程图
处理过程大致分为如下几个步骤:
(1)Receive状态,也就是请求处理的入口状态,根据VCL规则判断该请求应该是Pass或Pipe,或者进入Lookup(本地查询)。
(2)Lookup状态,进入此状态后,会在hash表中查找数据,若找到,则进入Hit状态,否则进入miss状态。
(3)Pass状态,在此状态下,会进入后端请求,即进入fetch状态。
(4)Fetch状态,在Fetch状态下,对请求进行后端的获取,发送请求,获得数据,并进行本地的存储。
(5)Deliver状态, 将获取到的数据发送给客户端,然后完成本次请求。
3、内置公用变量
VCL内置的公用变量可以用在不同的VCL函数中,根据这些公用变量使用的不同阶段,下面依次介绍。
当请求到达后,可以使用的公用变量如表1所示:
表1
公用变量名称 含义
req.backend 指定对应的后端主机
server.ip 表示服务器端IP
client.ip 表示客户端IP
req.request 指定请求的类型,例如GET、HEAD、POST等
req.url 指定请求的地址
req.proto 表示客户端发起请求的HTTP协议版本
req.http.header表示对应请求中的http头部信息
req. restarts 表示请求重启的次数,默认最大值为4
Varnish 在向后端主机请求时,可以使用的公用变量如表2所示:
表2
公用变量名称含义
beresp.request指定请求的类型,例如GET、HEAD等
beresp.url指定请求的地址
beresp .proto表示客户端发起请求的HTTP协议版本
beresp .http.header表示对应请求中的http头部信息
beresp .ttl表示缓存的生存周期,也就是cache保留多长时间,单位是秒
从cache或者后端主机获取内容后,可以使用的公用变量如表3所示:
表3
公用变量名称含义
obj.status表示返回内容的请求状态代码,例如200、302、504等
obj.cacheable表示返回的内容是否可以缓存,也就是说,如果HTTP返回是200、203、300、301、302、404、410等,并且有非0的生存期,则可以缓存
obj.valid表示是否是有效的HTTP应答
obj.response表示返回内容的请求状态信息
obj.proto表示返回内容的HTTP协议版本
obj.ttl表示返回内容的生存周期,也就是缓存时间,单位是秒
obj.lastuse表示返回上一次请求到现在的间隔时间,单位是秒
对客户端应答时,可以使用的公用变量如表4所示:
表4
公用变量名称含义
resp.status表示返回给客户端的HTTP状态代码
resp.proto表示返回给客户端的HTTP协议版本
resp.http.header表示返回给客户端的HTTP头部信息
resp.response表示返回给客户端的HTTP状态信息
在上面的讲述中,我们只是介绍了常用的VCL内置公用变量,如果需要了解和使用更多的公用变量信息,请登录varnish官方网站查阅。
六、Varnish 的 Storage 方式可分为两种:
(1)Malloc 通过 malloc 获取内存;
(2)Mmap file 创建大文件,通过二分法分段映射成 1G 以内的大块。
以 Mmap file 的缓存方式启动 I/O 也会形成瓶颈,原因主要是 Varnish 缓存的数据先会刷到磁盘上,然后在一次性读到内存中,这在访问量大的时候同时也会对 I/O造成很大的压力。Malloc 缓存方式虽然对 I/O 没有压力,因所有缓存数据都写到内存中。
七、配置一个简单的Varnish实例
由于版本的不同,Varnish配置文件的写法也存在一定差异,这里讲述的版本是基于centos 7.3版本的varnish4.0,但是该配置文件一定要以非注释行vcl 4.0开始,否则服务将不能识别。
Varnish安装完成后,默认的配置文件为/usr/local/varnish/etc/varnish/default.vcl,配置完成的default.vcl文件如下:
vcl4.0;##############启用负载均衡模块###############importdirectors;##############配置健康状态探测##############probebackend_healthcheck{.url="/index.html";.window=5;#窗口.threshold=2;#门槛.interval=3s;.timeout=1s;}#############添加后端主机################backendweb1{.host="172.17.254.17";.port="80";.probe=backend_healthcheck;}backendimg1{.host="172.17.254.107";.port="80";.probe=backend_healthcheck;}#############定义负载均衡及算法###############subvcl_init{newweb_cluster=directors.random();web_cluster.add_backend(web1,10);newimg_cluster=directors.round_robin();img_cluster.add_backend(img1);}################定义Purge-ACL控制#######################aclpurgers{#定义可访问来源IP"127.0.0.1";"172.17.0.0"/16;}################定义vcl_recv函数段######################subvcl_recv{if(req.method=="GET"&&req.http.cookie){return(hash);}#####如果请求不是GET或者HEAD,不缓存######if(req.method!="GET"&&req.method!="HEAD"){return(pass);}#####不正常的请求不缓存#####if(req.method!="GET"&&req.method!="HEAD"&&req.method!="PUT"&&req.method!="POST"&&req.method!="TRACE"&&req.method!="OPTIONS"&&req.method!="PURGE"&&req.method!="DELETE"){return(pipe);}if(req.url~"index.php"){return(pass);}if(req.method=="PURGE"){#PURGE请求的处理if(client.ip~purgers){#return(synth(405,"Methodnotallowed"));return(purge);}}##为发往后端主机的请求添加X-Forward-For首部##if(req.http.X-Forward-For){setreq.http.X-Forward-For=req.http.X-Forward-For+","+client.ip;}else{setreq.http.X-Forward-For=client.ip;}#####实现动静分离#####setreq.http.X-Forward-For=client.ip;if(req.url~"(?i)\.(jpeg|jpg|png|jif)($|\?)"){setreq.backend_hint=img_cluster.backend();}####################定义vcl_hash函数段#################if(req.http.host~"(?i)^(www.)?aaa.com$"){#根据不同的访问域名,分发至不同的后端主机组setreq.backend_hint=web_cluster.backend();}elsif(req.http.host~"(?i)^images.aaa.com$"){setreq.backend_hint=img_cluster.backend();}return(hash);}subvcl_hash{hash_data(req.url);}##############设置资源缓存时长#################subvcl_backend_response{#自定义缓存文件的缓存时长,即TTL值if(bereq.url~"\.(jpg|jpeg|gif|png)$"){setberesp.ttl=10s;}if(bereq.url~"\.(html|css|js)$"){setberesp.ttl=1200s;}#if(beresp.http.Set-Cookie){#定义带Set-Cookie首部的后端响应不缓存,直接返回给客户端setberesp.grace=30m;return(deliver);#}}subvcl_deliver{if(obj.hits>0){#为响应添加X-Cache首部,显示缓存是否命中setresp.http.X-Cache="HITfrom"+server.ip;}else{setresp.http.X-Cache="MISS";}unsetresp.http.X-Powered-By;unsetresp.http.Via;}
在经过以上的配置之后会出现一下测试界面:
650) this.width=650;" src="https://s4.51cto.com/oss/201711/14/464c9dc6177301679dc868e5a8af19a7.jpg" title="360截图20171114202003423.jpg" alt="464c9dc6177301679dc868e5a8af19a7.jpg" />
以上只是个人见解,有什么错误还望各位大神前来指教哦650) this.width=650;" src="http://img.baidu.com/hi/jx2/j_0058.gif" alt="j_0058.gif" />
本文出自 “Linux探索之旅” 博客,请务必保留此出处http://jieruma.blog.51cto.com/13158701/1981815
HTTP加速器——VARNISH
原文地址:http://jieruma.blog.51cto.com/13158701/1981815