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项目是2006年发布的第一个版本0.9.距今已经八年多了,此文档之前也提过varnish还不稳定,那是2007年时候编写的,经过varnish开发团队和网友们的辛苦耕耘,现在的varnish已经很健壮。很多门户网站已经部署了varnish,并且反应都很好,甚至反应比squid还稳定,且效率更高,资源占用更少。相信在反向代理,web加速方面,varnish已经有足够能力代替squid。
varnish的官网为https://www.varnish-cache.org,rpm,rpm包的下载位置为:http://repo.varnish-cache.org。
二、关于Varnish
1.varnish系统架构
varnish主要运行两个进程:Management进程和Child进程(也叫Cache进程)。
Management进程主要实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等。Management进程会每隔一段时间探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Mangagement将会重启此Child进程。
Child进程包含多种类型的线程,常见的如:
Acceptor进程:接受新的连接请求并响应
worker进程:child进程会为每个用户启动一个worker进程,因此,在高并发的场景中可能会出现数百个worker进程甚至更多
Expiry进程:从缓存中清理过期内容
Varnish依赖“工作区(workspace)”以降低线程在申请或修改内存时出现竞争的可能性。在varnish内部有多种不同的工作区,其中最关键的当属用于管理会话数据的session工作区
2.varnish日志
为了与系统的其他部分进行交互,Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log),因此,如果某线程需要记录信息,其仅需要持有一个锁,而后向共享内存中的某内存区域写入数据,再释放持有的锁即可。而为了减少竞争,每个worker线程都使用了日志数据缓存
共享内存大小一般为90M,其分为两部分,前一部分为计数器,后半部分为客户端请求的数据。varnish通过了多个不同的工具,如varnishlog、varnishncsa或varnishstst等来分析共享内存日志中的信息并能够以指定的方式进行显示
3.varnish的后端存储
varnish支持多种不同类型的后端存储。这可以在varnish启动时使用-s选项指定。后端存储的类型包括
(1)file:使用特定的文件存储全部的缓存数据,并通过操作系统的mmap()系统调用整个缓存文件映射至内存区域(如果条件允许)
(2)mallco: 使用mallco()库调用在varnish启动时向操作系统申请指定的大小的内存空间以存储缓存数据
(3)persistent(experimental):与file的功能相同,但是可以持久存储数据(即重启varnish时数据不会被清楚),仍处于测试阶段
varnish无法追踪某缓存对象是否存入了缓存文件,而后也就无法得知磁盘上的缓存文件是否可用,因此,file存储在varnish停止或重启是会清除数据。而persistent方法的出现对此有一个弥补,但persistent仍处于测试阶段,例如目前尚无法有效处理要缓存对象总体大小超出缓存空间的情况,所有,其仅适用于有着巨大缓存空间的场景。
选择使用合适的存储方式有助于途胜系统性能,从经验的角度来看,建议在内存空间足以存储所有数据的缓存对象时使用malloc的方法,反之,file存储将会有着更好的性能表现,然而,需要注意的是,varnishd实际上是用的空间比使用-s选项指定的缓存空间更大,一般说来,其需要为每个缓存对象多使用差不多1k左右的存储空间,这意味着,对于100万个缓存对象来说,其使用的缓存空间将超出指定大小1G左右,另外,为了保存数据结构等,varnish自身也会占去不少的内存空间。
为varnish指定使用的缓存类型时,-s选项可接受的参数格式如下:
malloc[,size]或file[,path[,size[,granularity]]]或persistent,path,size{experimental}
三、VCL
1.简介
VCL(Varnish Configuration Language)是varnish配置缓存策略的工具,它是一种基于“域”(domain specific)的简单编程语言,他支持有限的算术运算和逻辑运算操作、允许使用正则表达式进行字符串匹配、允许用户使用set自定义变量、支持if判断语句,也要内置的函数和变量等。使用VCL编写的缓存策略通常保存至.vcl文件中,其需要编译成二进制的格式后才能有varnish调用。事实上,整个缓存策略就是由几个特定的子历程如vcl_recv、vcl_fetch等组成,他们分别在不同的位置(或时间)执行,如果没有实现为某个位置自定义子例程,varnish将会执行默认的定义
VCL策略在启用前,会由management进程将其转换为C代码,而后再有gcc编译器将C代码编译成二进制程序。编译完成后,management负责将其连接至varnish实例,即Child进程。正式由于编译工作在child进程之外完成,它避免了转载错误格式VCL的风险,因此,varnish修改配置的开销非常小,其可以同时保有几分尚在引用的旧版本配置,也能够让新的配置即刻生效,编译后的旧版本配置通常在varnish重启时才会被丢弃,如果需要手动清理,则可以使用varnishadm的vcl.discard命令来完成
2.VCL状态引擎
在VCL状态引擎中,状态之间具有相关性,但彼此间互相隔离,每个引擎使用return(x)来退出当前状态并指示varnish进入下一个状态
varnish开始处理一个请求时,首先需要分析HTTP请求本身,比如从首部获取请求方法、验证其是否为一个合法的HTTP请求等,当这些基本分析结束后就需要做出第一个决策,即varnish是否从缓存中查找请求的资源,这个决定的实现则需要有VCL来完成,简单来说,要有vcl_recv方法来完成,如果说管理员没有定义vcl_recv函数,varnish将会执行默认的vcl_recv函数,然而,即便管理员自定义了vcl_recv,但如果没有为自定义的vcl_recv函数指定其终止操作(terminating),其仍将会指定默认的vcl_recv函数,事实上,varnish官方强烈建议让varnish执行默认的vcl_recv以便处理自定义vcl_recv函数中可能出现的漏洞
3.VCL语法
VCL的设计参考了C和perl语言,因此,对有着C或Perl编程经验者来说,其非常容易理解。其基本语法说明如下:
(1)//、#或/* comment */用于注释
(2)sub $name 定义函数
(3)不支持循环,有内置变量
(4)使用终止语句,没有返回值
(5)域专用
(6)操作符:=(赋值)、==(等值比较)、~(模式匹配)、!(非,取反)、&&(逻辑与)、||(逻辑或)
VCL的函数不接受参数并且没有返回值,因此,其并非真正意义上的函数,这也限定了VCL内部的数据传递只能隐藏在HTTP首部内部进行。VCL的return语句用于将控制权从VCL状态引擎返回给varnish,而非默认函数,这就是为什么VCL只有终止语句而没有返回值的原因,同时,对于每个“域”来说,可以定义一个或多个终止语句,以告诉varnish下一步采取何种操作,如查询缓存或不查询缓存
4.VCL的内置函数
VCL提供了结果函数来实现字符串的修改,如添加bans,重启VCL状态引擎因将控制权转回varnish等
regsub(str,reget,sub):基于正则表达式搜索指定的字符串并将其替换成指定的字符串,只替换匹配到的第一个
regsuball(str,reget,sub):基于正则表达式搜索指定的字符串并将其统统替换成指定的字符串
ban(expression):
ban_url(regex):Bans所有其URL能够由regex匹配的缓存对象
purge:从缓存中挑选出某对象以及其相关变种一并删除,这可以通过通过HYTP协议的PURGE方法完成
hash_data(str):
return():当某个VCL与运行结束时,将控制权返回给Varnish,并指示Varnish如何进行后续的操作:其可以返回的指令包括:lookup、pass、pipe、hit_for_pass、fetch、deliver和hash等:但某特定域可能技能返回某些特定的指令,而非前面列出的全部指令:
return(restart):重新运行整个VCL,即重新从vcl_recv开始进行处理;每一次重启都会增加req.restaets变量中的值,而max_restaets参数则用于限定最大重启次数
5.vcl_recv
vcl_recv是在varnish完成对请求报文的解码为基本数据结构后第一个要指定的子例程,他通常有四个主要用途:
(1)修改客户端数据以减少缓存对象差异性,比如删除URL中的www.等字符串
(2)基于客户端数据选用缓存策略:比如仅缓存特定的额URL请求、不缓存POST请求等
(3)为某web应用程序执行URL重写
(4)挑选合适的后端服务器;
可以使用下面的终止语句,即通过return()向varnish返回指示操作
pass:绕过缓存,即不从缓存中查询内容或不将内容存储至缓存中;
pipe:不对客户端进行检查或做出任何操作,而是在客户端与后端服务器之间建立专业“通道”,并直接将数据在二者之间进行传送:此时,keep-alive连接中后续传送的数据也都将在通过此管道进行直接传送,并不会出现在任何日志中
lookup:在缓存中查找用户请求的对象,如果缓存中没有其指定的对象,后续操作很可能会将其请求的对象进行缓存
error:有varnish自己合成一个响应报文,一般是响应一个错误类信息、重定向类信息或缓存均衡器返回的后端web服务器健康状态检查类信息
vcl_recv也可以通过精巧的策略完成一定意义上的安全功能,以将某特定的攻击扼杀于摇篮中,同时,它也可以检查出一些拼写的错误并将其进行修改
varnish默认的vcl_recv专门设计用来实现安全的缓策略,它主要完成两种功能:
(1)仅处理可以识别的HTTP方法,并且只缓存GET和HEAD方法
(2)不缓存任何用户特有的数据
安全起见,一般都在自定义的vcl_recv中不要使用return()终止语句,而是再由默认vcl_recv进行处理,并有其做出响应的的处理决策
6.vcl_fetch
如前面所述,想对于vcl_recv是根据客户端的请求做出缓存策略来说,vcl_fetch则是根据服务器端的响应做出缓存决策,在任何VCL状态引擎中发挥pass操作都将有vcl_fetch进行后续处理。vcl_fetch中有许多可用的内置变量,比如最常见的用于定义某对象缓存时长的beresp.ttl变量,通过return()返回给varnish的操作指令有:
deliver:缓存此对象,并将其发送给客户端(经由vcl_deliver)
hit_for_pass:不缓存此对象,但可以导致后续对此对象的请求直接送达到vcl_pass进行处理
restart:重启整个VCL,并增加重启次数,超出max_restarts限定的最大重启次数将会发挥错误信息
error code [reson]:返回指定的错误代码给客户端并丢弃此请求,“code”是错误标识,例如200、405等,“reason”是错误提示信息。
默认的vcl_fetch放弃了缓存任何使用了Set-Cookie首部的响应
7.vcl_deliver
在缓存中找到缓存内容,发送给客户端时调用此参数,通过return()返回给varnish的操作指令有:
deliver:缓存此对象,并将其发送给客户端(经由vcl_deliver)
error code [reson]:返回指定的错误代码给客户端并丢弃此请求,“code”是错误标识,例如200、405等,“reason”是错误提示信息。
8.val_pass
此函数在进入pass模式时被调用,用于将请求直接传递至后端主机,后端主机应答数据后发送给客户端,但是不缓存任何数据,在当前连接下,每次都是犯回最新的内容,通过return()返回给varnish的操作指令有:
error code [reson]:返回指定的错误代码给客户端并丢弃此请求,“code”是错误标识,例如200、405等,“reason”是错误提示信息。
pass:绕过缓存,即不从缓存中查询内容或不将内容存储至缓存中;
9.vcl_pipe
不对客户端进行检查或做出任何操作,而是在客户端与后端服务器之间建立专业“通道”,并直接将数据在二者之间进行传送:此时,keep-alive连接中后续传送的数据也都将在通过此管道进行直接传送,并不会出现在任何日志中,通过return()返回给varnish的操作指令有:
error code [reson]:返回指定的错误代码给客户端并丢弃此请求,“code”是错误标识,例如200、405等,“reason”是错误提示信息。
pipe:不对客户端进行检查或做出任何操作,而是在客户端与后端服务器之间建立专业“通道”,并直接将数据在二者之间进行传送:此时,keep-alive连接中后续传送的数据也都将在通过此管道进行直接传送,并不会出现在任何日志中
10.lookup
表示在缓存里查找被请求的对象,并且根据查找的数据把控制权交给vcl_miss或vcl_hit
11.vcl_hit
在执行lookup指令后,如果在缓存中找到请求的内容,将自动调用此函数,通过return()返回给varnish的操作指令有:
deliver:缓存此对象,并将其发送给客户端(经由vcl_deliver)
error code [reson]:返回指定的错误代码给客户端并丢弃此请求,“code”是错误标识,例如200、405等,“reason”是错误提示信息。
pass:绕过缓存,即不从缓存中查询内容或不将内容存储至缓存中;
12.vcl_miss函数
在执行lookup指令后,如果在缓存中找不到请求的内容,将自动调用此函数,此函数可以判断是否在后端服务器上获取内容,通过return()返回给varnish的操作指令有:
error code [reson]:返回指定的错误代码给客户端并丢弃此请求,“code”是错误标识,例如200、405等,“reason”是错误提示信息。
pass:绕过缓存,即不从缓存中查询内容或不将内容存储至缓存中;
13.VCL处理流程图
通过上面对VCL函数的介绍,大家应该对每个函数实现的功能有一个了解,,起始每个函数之间是有联系的,如下图所示
状态引擎:
1:vcl_recv 2:vcl_pipe 3:vcl_pass 4:vcl_hash 5:vcl_hit 6:vcl_miss 7:vcl_fetch 8:vcl_delier
9:vcl_error
缓存的处理步骤:
接受请求---解析请求---查询缓存---新鲜度检查---创建响应报文---发送响应---记录日志
缓存的新鲜度检测方法:
(1)过期时间:
HTTP/1.0
Expires:"Mon, 21 Mar 2016 05:02:19 GMT" 固定时间来检测
HTTP/1.1
Cache-Control:"max-age=900" 这种最多存活时时间来检测
(2)有效性再验证:revalidate
如果原始内容发生改变,就正常响应,响应码200
如果原始内容没改变,则仅相应首部(不带body部分),相应码304(Not Modified)
如果原始内容消失,响应为404,些时缓存中cache object 也应该被删除
(3)条件式请求首部:
根据时间戳判断:
If-Modified-Since: 自从请求的时间之后,请求的资源是否发生过修改,用时间戳验证
If-Unmodified-Since:自从请求的时间之后,请求的资源是否发没有修改
根据标签来判断:
If-None-Match :本地缓存中存储的文档的Etag标签是否与服务器文档的Etag不匹配。
If-Match :本地缓存中存储的文档的Etag标签是否与服务器文档的Etag匹配。
yum 安装 varnish
# yum insatll varnish-libs-3.0.4-1.el6.x86_64.rpm varnish-3.0.4-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-3.0.5-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-libs-3.0.5-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-docs-3.0.5-1.el6.x86_64.rpm
1:
# vi /etc/sysconfig/
var
nish
修改一下参数
VARNISH_LISTEN_PORT=80 //表示将varnish对外的监听端口改为80
VARNISH_STORAGE="malloc,100M"
//将数据缓存在内存中,内存大小为100M
其余的使用默认即可
2:
配置varnish
本处使用varnishadm命令行接口来刷新varnish
命令格式:varnishadm [-n ident] [-t timeout] [-S secretfile] -T [address]:port command [...]
通过命令行的方式连接至varnishd进行管理操作的工具,指定要连接的varnish实例有两种方法:
-T [address]:port 来接指定套接字上的实例
-n ident 连接指定名称的实例
其运行模式有两种,当不在命令行中给出指定要指定的“command”时,要将进入交互模式,否则,varnish将指定指定的“command”并退出。
# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnishadm 使用:
vcl.load
vcl.use
vcl.show
vcl.discard
varnish 一般只对 get head 缓存
backend storage:支持缓存存储内型有3种
-s type
malloc [,size] //内存中缓存
file[,path[,size[,granularity]]] //一个文件保存所有缓存
persistent,path,size {experimental} // 在具体生并环境中不建议用,
在varnishl 里可用单分支和多分支判断
varnish 里可用变量:
1:常用变量,在任何引擎中都可以用的,
new // 获取当前系统的当前时间
.host //后端主机的ip
.port //后断主机的端口
2:用于处理请求阶段
client.ip // 客户机ip
server.hostname // 服务器主机名(varnish服务器名)
server.ip // 服务器主ip (varnish ip)
server.port //服务器端口 (varnish 端口)
req.request //请求方法
req.url // 请求url
req.porto //请求协议
req.backend //用于服务此次请求的后端主机
req.backend.healthy //后端健康状态
req.http.HEADER //引用请求报文中指定的首部
req.hash-always_miss
req.hash-ignore_busy
req.can_gzip //客户端是否能接受gzip 压缩的内容
req.restarts //此请求被重启的请求
3: varnish自己 向backend 主机发起请求前可用的变量
bereq.request //varnish 对后端口请求方法
bereq.url //varnish 对后端口请求url
bereq.proto //varnish 对后端请求协议
bereq.http.HEADER //varnish 对后端口请求头
bereq.connect_timeout //等待与backend主机发起的连接超时时长
4:backend主机的响应报文到达varnish主机后,将其放放置于cache中之前可用的变量。
beresp.do_stream // 流式响应
beresp.do_gzip // 是否压缩后存入cache
beresp.do_gunzip // 是否解压后存入缓存。
beresp.http.HEADER // 响应时头
beresp.proto // 响应时协议
beresp.status // 响应状态码
beresp.response // 响应时的原因短语
beresp.ttl // 响应对象的剩余生存时长,单位为秒
beresp.backend.name // 相应报文来源的backend名称
beresp.backend.ip // 响应时报文来源的backend IP
beresp.backend.port // 响应时报文来源的backend 端口
beresp.storage //响应的存储后端
5:缓存对象存入的ccache之后可用的变量
obj,proto //响应时协议
obj.status // 响应时状态码
obj.response
obj.hits //响应时次数
obj.ttl
obj,http,HEADER // 响应首部
6:在决定对请求键做hash计算时可用的变量
req.hash
7:在为客户端准备响应时报文可用变量
resp.proto
resp.status
resp.response
resp.http.HEADER
状态引擎:
vcl_init: 在装载vcl,用其处理请求之前
vcl_recv: 请求被接入,但在其分析,处理完成之前。
是否服务些请求,如何服务,使用那个后端主机服务
vcl_fetch:从后端口主机收到相应报文之前被调用
deliver
error code 给个错误码
restart 重启请求
warnish 的param的查看和修改:
varnish> param.show -l
修改链接池一些值,但是这种方法只对当前有效果
varnish> param.set thread_pool_max 4000 修改线程池个数
200
varnish 线程模型:
cache-worker 线程
cache-mian 线程:些线程只有一个,用来启动cache
ban luker:
acceptor:
epoll: 线程池管理
expire: 清理过期缓存
thread_pool_add_delay 2 [milliseconds]
thread_pool_add_threshold 2 [requests]
thread_pool_fail_delay 200 [milliseconds]
thread_pool_max 3000 [threads] 单个线程池启动最多线程个数
thread_pool_min 50 [threads]
thread_pool_purge_delay 1000 [milliseconds] 每一秒清理一次缓存,请保留默认
thread_pool_stack unlimited [bytes]
thread_pool_timeout 120 [seconds] 线程池的超时时间,
thread_pool_workspace 65536 [bytes] 线程池默认使用多少内存,建议默认
thread_pools 2 [pools] 线程池管理
thread_stats_rate 10 [requests]
varnish的命令行工具:
(1)varnishadm
(2)varnishtop:内存日志区域查看工具
RxHeader User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebK
it/53
RxHeader:为tag,基于标签过虑,可用-i或-x 选项,
User-Agent 为起始内容。称为日志消息。用-I或-X过滤
-I regexp:仅显示被模式匹配到的条目
-X regexp:仅显示不被模式匹配到的条目
-C:忽略大小写
-d:显示已有日志
(3)varnishstat 缓存统计
-l 列出所有字段
-f 统计字段 -f后接的字段名
-x:xml输出格式
-j:json 格式输出
配置文件:
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
return (deliver);
}
下面为varnish 配置样本
backend default {
.host = "192.168.1.105";
.port = "80";
}
acl purgers {
"127.0.0.1";
"192.168.1.0"/24;
}
#
# Below is a commented-out copy of the default VCL logic. If you
# redefine any of these subroutines, the built-in logic will be
# appended to your code.
sub vcl_recv {
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 == "PURGE") {
if (!client.ip ~ purgers) {
error 405 "Method not allowed";
}
return (lookup);
}
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);
}
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_pipe {
# # Note that only the first request to the backend will have
# # X-Forwarded-For set. If you use X-Forwarded-For and want to
# # have it set for all requests, make sure to have:
# # set bereq.http.connection = "close";
# # here. It is not set by default as it might break some broken web
# # applications, like IIS with NTLM authentication.
# return (pipe);
# }
#
sub vcl_pass {
if (req.request == "PURGE") {
error 502 "PURGE on a passed object";
}
return (pass);
}
#
# sub vcl_hash {
# hash_data(req.url);
# if (req.http.host) {
# hash_data(req.http.host);
# } else {
# hash_data(server.ip);
# }
# return (hash);
# }
#
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "Purged";
}
return (deliver);
}
sub vcl_miss {
if (req.request == "PURGE") {
purge;
error 404 "Not in cache";
}
return (fetch);
}
# sub vcl_fetch {
# if (beresp.ttl <= 0s ||
# beresp.http.Set-Cookie ||
# beresp.http.Vary == "*") {
# /*
# * Mark as "Hit-For-Pass" for the next 2 minutes
# */
# set beresp.ttl = 120 s;
# return (hit_for_pass);
# }
# return (deliver);
# }
#
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
return (deliver);
}
# sub vcl_error {
# set obj.http.Content-Type = "text/html; charset=utf-8";
# set obj.http.Retry-After = "5";
# synthetic {"
# <?xml version="1.0" encoding="utf-8"?>
# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
# "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
# <html>
# <head>
# <title>"} + obj.status + " " + obj.response + {"</title>
# </head>
# <body>
# <h1>Error "} + obj.status + " " + obj.response + {"</h1>
# <p>"} + obj.response + {"</p>
# <h3>Guru Meditation:</h3>
# <p>XID: "} + req.xid + {"</p>
# <hr>
# <p>Varnish cache server</p>
# </body>
# </html>
# "};
# return (deliver);
# }
#
# sub vcl_init {
# return (ok);
# }
#
# sub vcl_fini {
# return (ok);
配置范例2:
probe chk {
.url = "/test.html";
.window = 5;
.threshold = 3;
.interval = 3s;
.timeout = 1s;
}
backend web1 {
.host = "192.168.1.104";
.port = "80";
.probe = chk;
}
backend web2 {
.host = "192.168.1.105";
.port = "80";
.probe = chk;
}
director webservers random {
.retries = 5;
{
.backend = web1;
.weight = 1;
}
{
.backend = web2;
.weight = 1;
}
}
#
#
acl purgers {
"127.0.0.1";
"192.168.1.0"/24;
}
# Below is a commented-out copy of the default VCL logic. If you
# redefine any of these subroutines, the built-in logic will be
# appended to your code.
sub vcl_recv {
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 ~ "test.html") {
set req.backend = web1;
} else {
set req.backend = webservers;
}
if (req.request == "PURGE") {
if (!client.ip ~ purgers) {
error 405 "Method not allowed";
}
return (lookup);
}
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);
}
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_pipe {
# # Note that only the first request to the backend will have
# # X-Forwarded-For set. If you use X-Forwarded-For and want to
# # have it set for all requests, make sure to have:
# # set bereq.http.connection = "close";
# # here. It is not set by default as it might break some broken web
# # applications, like IIS with NTLM authentication.
# return (pipe);
# }
#
sub vcl_pass {
if (req.request == "PURGE") {
error 502 "PURGE on a passed object";
}
return (pass);
}
#
# sub vcl_hash {
# hash_data(req.url);
# if (req.http.host) {
# hash_data(req.http.host);
# } else {
# hash_data(server.ip);
# }
# return (hash);
# }
#
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "Purged";
}
return (deliver);
}
sub vcl_miss {
if (req.request == "PURGE") {
purge;
error 404 "Not in cache";
}
return (fetch);
}
# sub vcl_fetch {
# if (beresp.ttl <= 0s ||
# beresp.http.Set-Cookie ||
# beresp.http.Vary == "*") {
# /*
# * Mark as "Hit-For-Pass" for the next 2 minutes
# */
# set beresp.ttl = 120 s;
# return (hit_for_pass);
# }
# return (deliver);
# }
#
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
return (deliver);
}
# sub vcl_error {
# set obj.http.Content-Type = "text/html; charset=utf-8";
# set obj.http.Retry-After = "5";
# synthetic {"
# <?xml version="1.0" encoding="utf-8"?>
# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
# "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
# <html>
# <head>
# <title>"} + obj.status + " " + obj.response + {"</title>
# </head>
# <body>
# <h1>Error "} + obj.status + " " + obj.response + {"</h1>
# <p>"} + obj.response + {"</p>
# <h3>Guru Meditation:</h3>
# <p>XID: "} + req.xid + {"</p>
# <hr>
# <p>Varnish cache server</p>
# </body>
# </html>
# "};
# return (deliver);
# }
#
# sub vcl_init {
# return (ok);
# }
#
# sub vcl_fini {
# return (ok);
# }