Linux之varnish
一:varnish简介
Varnish是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好
Varnish 的作者Poul-Henning Kamp是FreeBSD的内核开发者之一,他认为现在的计算机比起1975年已经复杂许多。在1975年时,储存媒介只有两种:内存与硬盘。但现在计算机系统的内存除了主存外,还包括了CPU内的L1、L2,甚至有L3快取。硬盘上也有自己的快取装置,因此Squid Cache自行处理物件替换的架构不可能得知这些情况而做到最佳化,但操作系统可以得知这些情况,所以这部份的工作应该交给操作系统处理,这就是 Varnish cache设计架构.
二:varnish设计机构图
三:VCL 处理流程
Varnish 处理 HTTP 请求的过程大致分为如下几个步骤。
- Receive 状态(vcl_recv)。也就是请求处理的入口状态,根据 VCL 规则判断该请求应该 pass(vcl_pass)或是 pipe(vcl_pipe),还是进入 lookup(本地查询)。
- Lookup 状态。进入该状态后,会在 hash 表中查找数据,若找到,则进入 hit(vcl_hit)状态,否则进入 miss(vcl_miss)状态。
- Pass(vcl_pass)状态。在此状态下,会直接进入后端请求,即进入 fetch(vcl_fetch)状态
- Fetch(vcl_fetch)状态。在 fetch 状态下,对请求进行后端获取,发送请求,获得数据,并根据设置进行本地存储。
- Deliver(vcl_deliver)状态。将获取到的数据发给客户端,然后完成本次请求
1) VCL 内置函数
vcl_recv 函数
用于接收和处理请求。当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求。例如如何响应、怎么响应、使用哪个后端服务器等。
此函数一般以如下几个关键字结束。
pass:表示进入 pass 模式,把请求控制权交给 vcl_pass 函数。
pipe:表示进入 pipe 模式,把请求控制权交给 vcl_pipe 函数。
lookup:表示进入 lookup 模式,把请求控制权交给 lookup 指令处理,在缓存中查找被请求的对象,并且根据查找的结果把控制权交给函数 vcl_hit 或函数 vcl_miss。
error code [reason]:表示返回“code”给客户端,并放弃处理该请求。“code”是错误标识,例如 200 和 405 等。“reason”是错误提示信息.
vcl_pipe 函数
此函数在进入 pipe 模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,将不变的内容返回给客户端,直到这个连接被关闭。
此函数一般以如下几个关键字结束。
error code [reason]。
pipe
vcl_pass 函数
此函数在进入 pass 模式时被调用,用于将请求直接传递至后端主机。后端主机在应答数据后将应答数据发送给客户端,但不进行任何缓存,在当前连接下每次都返回最新的内容。
此函数一般以如下几个关键字结束。
error code [reason]。
pass。
restart 重新启动流程,增加启动次数,如果重新启动次数高于 max_restarts 发出一个错误警告
vcl_hash
当您想把一个数据添加到 hash 上时,调用此函数。
此函数一般以如下几个关键字结束
vcl_hit 函数
在执行 lookup 指令后,在缓存中找到请求的内容后将自动调用该函数。
此函数一般以如下几个关键字结束。
deliver:表示将找到的内容发送给客户端,并把控制权交给函数 vcl_deliver。
error code [reason] 。
pass。
restart 重新启动流程,增加启动次数,如果重新启动次数高于 max_restarts 发出一个错误警告
vcl_miss 函数
在执行 lookup 指令后,在缓存中没有找到请求的内容时自动调用该方法。此函数可用于判断是否需要从后端服务器获取内容。
此函数一般以如下几个关键字结束。
fetch:表示从后端获取请求的内容,并把控制权交给 vcl_fetch 函数。
error code [reason] 。
pass。
vcl_fetch 函数
在后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端。
此函数一般以如下几个关键字结束。
error code [reason]。
pass。
deliver。
esi。
restart 重新启动流程,增加启动次数,如果重新启动次数高于 max_restarts 发出一个错误警告
vcl_deliver 函数
将在缓存中找到请求的内容发送给客户端前调用此方法。
此函数一般以如下几个关键字结束。
error code [reason]。
deliver。
restart 重新启动流程,增加启动次数,如果重新启动次数高于 max_restarts 发出一个错误警告
vcl_error
出现错误时调用此函数。
此函数一般以如下几个关键字结束。
deliver。
restart
2)工作流程概述
Varnish 与一般服务器软件类似,分为 master 进程和 child 进程。Master 进程读入存储配置文件,调用合适的存储类型,然后创建 / 读入相应大小的缓存文件,接着 master 初始化管理该存储空间的结构体,然后 fork 并监控 child 进程。Child 进程在主线程的初始化的过程中,将前面打开的存储文件整个 mmap 到内存中,此时创建并初始化空闲结构体,挂到存储管理结构体,以待分配。Child 进程分配若干线程进行工作,主要包括一些管理线程和很多 worker 线程。
接着,开始真正的工作,varnish 的某个负责接收新 HTTP 连接线程开始等待用户,如果有新的 HTTP 连接过来,它总负责接收,然后唤醒某个等待中的线程,并把具体的处理过程交给它。Worker 线程读入 HTTP 请求的 URI计算出响应的hash值,查找已有的 object,如果命中则直接返回并回复用户。如果没有命中,则需要将所请求的内容,从后端服务器中取过来,存到缓存中,然后再回复。
分配缓存的过程是这样的:它根据所读到 object 的大小,创建相应大小的缓存文件。为了读写方便,程序会把每个 object 的大小变为最接近其大小的内存页面倍数。然后从现有的空闲存储结构体中查找,找到最合适的大小的空闲存储块,分配给它。如果空闲块没有用完,就把多余的内存另外组成一个空闲存储块,挂到管理结构体上,这样做可以减少磁盘碎片。如果缓存已满,就根据 LRU(最近做少使用原则) 机制,把最旧的 object 释放掉。
释放缓存的过程是这样的:有一个超时线程,检测缓存中所有 object 的生存期,如果超初设定的 TTL(Time To Live)没有被访问,就删除之,并且释放相应的结构体及存储内存。注意释放时会检查该存储内存块前面或后面的空闲内存块,如果前面或后面的空闲内存和该释放内存是连续的,就将它们合并成更大一块内存。
整个文件缓存的管理,没有考虑文件与内存的关系,实际上是将所有的 object 都考虑是在内存中,如果系统内存不足,系统会自动将其换到 swap 空间,而不需要 varnish 程序去控制。
四:VCL的内置公共变量
1)当请求到达时,可以使用的公共变量
2)对客户端相应时可使用公共变量
3)后端主机获取内容时可使用公共变量
五:varnish试验
1)试验拓扑
2)查看安装的配置文件
[root@varnish ~]# rpm -ql varnish /etc/logrotate.d/varnish /etc/rc.d/init.d/varnish #启动脚本 /etc/rc.d/init.d/varnishlog /etc/rc.d/init.d/varnishncsa /etc/sysconfig/varnish #启动脚本的配置文件 /etc/varnish #全局配置文件 /etc/varnish/default.vcl #默认VCL /usr/bin/varnish_reload_vcl #varnish管理工具 /usr/bin/varnishadm /usr/bin/varnishhist /usr/bin/varnishlog /usr/bin/varnishncsa /usr/bin/varnishreplay /usr/bin/varnishsizes /usr/bin/varnishstat /usr/bin/varnishtest /usr/bin/varnishtop /usr/lib64/varnish /usr/lib64/varnish/libvarnish.so /usr/lib64/varnish/libvarnishcompat.so /usr/lib64/varnish/libvcl.so /usr/lib64/varnish/libvgz.so /usr/lib64/varnish/vmods /usr/lib64/varnish/vmods/libvmod_std.so /usr/sbin/varnishd /usr/share/doc/varnish-3.0.4 /usr/share/doc/varnish-3.0.4/ChangeLog /usr/share/doc/varnish-3.0.4/LICENSE /usr/share/doc/varnish-3.0.4/README /usr/share/doc/varnish-3.0.4/README.redhat /usr/share/doc/varnish-3.0.4/examples /usr/share/doc/varnish-3.0.4/examples/default.vcl /usr/share/doc/varnish-3.0.4/examples/zope-plone.vcl /usr/share/man/man1/varnishadm.1.gz #man配置文件 /usr/share/man/man1/varnishd.1.gz /usr/share/man/man1/varnishhist.1.gz /usr/share/man/man1/varnishlog.1.gz /usr/share/man/man1/varnishncsa.1.gz /usr/share/man/man1/varnishreplay.1.gz /usr/share/man/man1/varnishsizes.1.gz /usr/share/man/man1/varnishstat.1.gz /usr/share/man/man1/varnishtest.1.gz /usr/share/man/man1/varnishtop.1.gz /usr/share/man/man3/vmod_std.3.gz /usr/share/man/man7/varnish-cli.7.gz /usr/share/man/man7/varnish-counters.7.gz /usr/share/man/man7/vcl.7.gz /var/lib/varnish /var/log/varnish #日志文件
3)修改启动脚本配置文件
[root@varnish sysconfig]# vim /etc/sysconfig/varnish VARNISH_LISTEN_PORT=80 #这里设置的监听端口设置为80 VARNISH_STORAGE="malloc,64M" #我们这里设置的是64M,因为我们这里是测试环境,在生产环境中可以根据实际需求设置很大
4)启动varnish
[root@varnish ~]# service varnish start Starting Varnish Cache: [确定]
5)配置后端http服务器
[root@web1 ~]# yum install -y httpd [root@web1 ~]# cat /var/www/html/index.html <h1>varnish server node1</h1> [root@web1 ~]# service httpd start 正在启动 httpd:
6)真假vcl配置文件
[root@varnish ~]# cd /etc/varnish/ [root@varnish varnish]# cp default.vcl test.vcl [root@varnish varnish]# vim test.vcl backend webserver { .host = "172.16.16.1"; .port = "80"; } sub vcl_recv { set req.backend = webserver; }
7)加载vcl配置文件
[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 200 ----------------------------- Varnish Cache CLI 1.0 ----------------------------- Linux,2.6.32-358.el6.x86_64,x86_64,-smalloc,-smalloc,-hcritbit varnish-3.0.4 revision 9f83e8f Type ‘help‘ for command list. Type ‘quit‘ to close CLI session. varnish> vcl.load test test.vcl #编译 200 VCL compiled. varnish> vcl.list 200 active 0 boot available 0 test varnish> vcl.use test 200
OK,进行测试一下
如何修改配置文件查看我们的缓存是否命中
1)修改配置文件
[root@varnish varnish]# vim test.vcl backend default { .host = "172.16.16.1"; .port = "80"; } sub vcl_recv { set req.backend = webserver; } #修改vcl_deliver增一个响应头部 sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "Hit from"+" "+server.ip; } else { set resp.http.X-Cache = "Miss via"+" "+server.ip; } }
第一次加载时缓存X-Cache为Miss(没有被命中).
第二次刷新加载时命中缓存此处的X-Cache为HIT.
如何设置让某个条件不被命中
1)修改配置文件
[root@varnish ~]# vim /etc/varnish/test.vcl backend webserver { .host = "172.16.16.1"; .port = "80"; } #设置条件让请求test.html文件时不缓存 sub vcl_recv { if (req.url ~ "^/test.html$") { return(pass); } set req.backend = webserver; } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "Hit from"+" "+server.ip; } else { set resp.http.X-Cache = "Miss via"+" "+server.ip; } } [root@web1 ~]# vim /var/www/html/test.html <h1>mandela</h1>
2)重新加载配置文件
varnish> vcl.load test2 test.vcl 200 VCL compiled. varnish> vcl.use test2 200
不管刷新多少次始终是不会对此网页信息进行缓存.
如何根据响应内容作出判断
修改配置文件
[root@varnish ~]# vim /etc/varnish/test.vcl backend webserver { .host = "172.16.16.1"; .port = "80"; } sub vcl_recv { if (req.url ~ "^/test.html$") { return(pass); } set req.backend = webserver; } sub vcl_fetch { if (req.request == "GET" && req.url ~ "\.(html|css|js|jpg|jpeg|png|gif)$") { set beresp.ttl = 3600s; } } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "Hit from"+" "+server.ip; } else { set resp.http.X-Cache = "Miss via"+" "+server.ip; } }
重新加载文件
varnish> vcl.load test3 test.vcl 200 VCL compiled. varnish> vcl.use test3 200
varnish如何实现负载均衡及检查后端主机状态
修改配置文件
[root@varnish ~]# vim /etc/varnish/test.vcl backend webserver1 { .host = "172.16.16.1"; .port = "80"; .probe = { .url = "/index.html"; .interval = 1s; .window = 3; .threshold = 1; } } backend webserver2 { .host = "172.16.16.4"; .port = "80"; .probe = { .url = "/index.html"; .interval = 1s; .window = 3; .threshold = 1; } } director webserver random { { .backend = webserver1; .weight = 3; } { .backend = webserver2; .weight = 1; } } sub vcl_recv { set req.backend = webserver; } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "Hit from"+" "+server.ip; } else { set resp.http.X-Cache = "Miss via"+" "+server.ip; } }
重新装载
varnish> vcl.load test4 test.vcl 200 VCL compiled. varnish> vcl.use test4 200
这样后端定义了两个主机16.1和16.2.且实现了轮训调度加缓存机制加后段的安全状态检测,后端的安全状态检测是每一秒检测一次,检测三次不在线就自动下线.判断在线次数只需要判断一次.
varnish> backend.list 200 Backend name Refs Admin Probe default(127.0.0.1,,80) 1 probe Healthy (no probe) webserver(172.16.16.1,,80) 4 probe Healthy (no probe) webserver1(172.16.16.1,,80) 3 probe Healthy 3/3 webserver2(172.16.16.4,,80) 3 probe Healthy 3/3
定义的后端主机分别是16.1和16.4
每隔一秒钟就检测一下后端主机是否在线.200状态码说明主机在线.
OK 我们的varnish配置基本完成.希望大家有些收获.
本文出自 “slayer” 博客,请务必保留此出处http://slayer.blog.51cto.com/4845839/1558268
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。