管理varnish以及清除内存等操作虽然可以使用varnishadm,但是这里推荐使用telnet,一个交互的管理界面。
比如: telnet 127.0.0.1 6082
之后,输入help会显示所有可用命令。
help [command] ping [timestamp] status start stop stats vcl.load vcl.inline vcl.use vcl.discard vcl.list vcl.show param.show [-l] [] param.set quit purge.url purge.hash purge [&& ]... purge.list
重新加载Varnish配置文件
telnet 127.0.0.1 6082 vcl.load newconfig /data/app/varnish/etc/varnish/default.vcl vcl.use newconfig
注意:varnish 的CLI可能需要认证,最简单的办法就是在varnish启动的时候取掉相应的参数。
-S /etc/varnish/secret \
参考 https://www.varnish-cache.org/docs/trunk/reference/varnish-cli.html
Varnish的缓存方式
Malloc (malloc) 通过 malloc 获取内存,简单,速度快
Mmap file (file) 创建文件缓存
这个是varnish缓存的两种方式,可以在启动的时候通过参数指定。
Varnish处理流程
首次请求时过程如下:
recv->hash->miss->fetch->deliver
缓存后再次请求:
recv->hash->hit->deliver(fetch的过程没了,这就是我们要做的,把要缓存的页面保存下来)
直接交给后端pass的情况:
recv->hash->pass->fetch->deliver(直接从后端获取数据后发送给客户端,此时Varnish相当于一个中转站,只负责转发)
VCL以及基本对象
request 从客户端进来
responses 从后端服务器过来
object 存储在cache中
VCL语言
req 请求目标,当varnish接收到一个请求,这时req object就被创建了,你在vcl_recv中的大部分工作,都是在req object上展开的。
beresp 后端服务器返回的目标,它包含返回的头信息,你在vcl_fetch中的大部分工作都是在beresp object上开展的。
obj 被cache的目标,只读的目标被保存于内存中,obj.ttl的值可修改,其他的只能读。
VCL支持一下运算符
= 赋值运算符
== 对比
~ 匹配,在ACL中和正则表达式中都可以用
! 否定
&& 逻辑与
|| 逻辑或
Grace mode
如果后端需要很长时间来生成一个对象,这里有一个线程堆积的风险。为了避免这 种情况,你可以使用 Grace。他可以让 varnish 提供一个存在的版本,然后从后端生成新 的目标版本。
当同时有多个请求过来的时候,varnish只发送一个请求到后端服务器,在“set beresp.grace = 30m; ”时间内复制旧的请求结果给客户端。
Saint mode
有时候,服务器很古怪,他们发出随机错误,您需要通知 varnish 使用更加优雅的方式处理 它,这种方式叫神圣模式(saint mode)。Saint mode 允许您抛弃一个后端服务器或者另一 个尝试的后端服务器或者 cache 中服务陈旧的内容。
Varnish代理
Varnish负载均衡
可以把多台 backends 聚合成一个组,这些组被叫做directors。这样可以增强性能和弹力。您可以定义多个backends和多个group在同一个directors。
健康检查
在之前的两个后端服务器上加上健康检查。
主备
后端备份。在recv里增加了
if (req.restarts == 0) {
set req.backend = backend1;
} else {
set req.backend = backend2;
}
在fetch里增加了
if (beresp.status != 200 && req.restarts == 0) {
restart;
}
或在error里加restart
重点参考:https://www.varnish-cache.org/docs/3.0/reference/vcl.html
注意事项:
1. Varnish的不同版本的配置不同,必须查阅官方文档。
比如,在2.x 直接用ESI表示启用ESI,在3.x就不是了。
2. Varnish 2.x有Cookie的问题,当Cookie过大,会产生503错误,升级varnish或者减少set_cookie的操作。
3. 启动varnishd的时候如果选用-s file方式,每次会重新建立缓存文件,而原来的文件不会删除,因此注意清除这些遗留文件。
注释完整的一段VCL文件参考
#设置后端服务器地址 backend default { .host = "127.0.0.1"; .port = "80"; } #允许刷新缓存的ip acl purgeAllow { "localhost"; "192.168.56.1"; } sub vcl_recv { #刷新缓存设置 if (req.request == "PURGE") { #判断是否允许ip if (!client.ip ~ purgeAllow) { error 405 "Not allowed."; } #去缓存中查找 return (lookup); } #首次访问增加X-Forwarded-For头信息,方便后端程序 #获取客户端ip if (req.restarts == 0) { #如果设置过此header则要再次附加上,用,隔开,如果 #只有一层代理的话,就无需设置了 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; } } #修正客户端的Accept-Encoding头信息,默认选用gzip方式 #防止个别浏览器发送类似 deflate, gzip #当然后端如果只支持gzip的话.可以只设置gizp if (req.http.Accept-Encoding) { if (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } #如果后端支持deflate方式,建议去掉,否则刷新缓存时 #需特殊处理 elsif (req.http.Accept-Encoding ~ "deflate") { set req.http.Accept-Encoding = "deflate"; } #其他的压缩方式忽略 else { remove req.http.Accept-Encoding; } } #静态文件和明确以.php结尾的url无需缓存, 建议把静态文件分离 #至单独服务器下,减少动态应用服务器压力,同时降低arnishd的压力 if(req.url ~ "\.(png|gif|jpg|css|js|php)$"){ return (pass); } #非正规的请求直接转发给后端服务器 if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" && req.request != "OPTIONS" && req.request != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } #只处理GET和HEAD请求,如果你不想缓存POST的页面话 if (req.request != "GET" && req.request != "HEAD") { return (pass); } #http认证的页面也pass if (req.http.Authorization) { return (pass); } return (lookup); } #管道?按官方文档说的是此模式下请求会原封不动的转交给后端知道连接关闭 sub vcl_pipe { return (pipe); } #交给后端服务器 sub vcl_pass { return (pass); } #缓存文件名的哈希处理 sub vcl_hash { #以url为hash set req.hash += req.url; #加上host if (req.http.host) { set req.hash += req.http.host; } #没有则取ip else { set req.hash += server.ip; } #支持压缩的要增加,防止发送给不支持压缩的浏览器压缩的内容 if(req.http.Accept-Encoding){ set req.hash += req.http.Accept-Encoding; } return (hash); } #缓存命中后的处理 sub vcl_hit { #如果不可缓存,直接交给后端 if (!obj.cacheable) { return (pass); } #如果为更新缓存的请求,则设置ttl为0,并告知客户端处理结果 if (req.request == "PURGE") { set obj.ttl = 0s; error 200 "Purged."; } set resp.http.X-Cache = "HIT“
return (deliver); } #缓存未命中 sub vcl_miss { #更新缓存的请求,提示缓存不存在Not in cache if (req.request == "PURGE") { error 404 "Not in cache."; } #既然缓存不存在了,就去后端取吧 return (fetch); } # sub vcl_fetch { #是否开启ESI功能(仅做演示用,单独给/esi-test.html开启esi) if (req.url == "/esi-test.html") { esi; } #如果后端返回不可缓存,直接pass if (!beresp.cacheable) { return (pass); } #/article/下的url缓存30分钟(演示用) if (req.url ~ "^/article/\d+\.html$"){ set beresp.ttl = 30m; } #/category/下的url缓存20分钟(演示用) if (req.url ~ "^/category/$"){ set beresp.ttl = 20m; } #如果后端发送了set-cookie头信息(如session会话开启),则不缓存 if (beresp.http.Set-Cookie) { return (pass); } return (deliver); } #发送给客户端 sub vcl_deliver { #去掉varnish中的一些头信息(如果你不想保留的话,建议保留Age,方便查看) #remove resp.http.X-Varnish; #remove resp.http.Via; return (deliver); } #定义错误页面的信息 sub vcl_error { #设置返回页面的类型及编码 set obj.http.Content-Type = "text/html; charset=utf-8"; #具体内容,可以更加自己的需要修改错误提示信息 synthetic {" HTTP ERROR "}; return (deliver); }
官方文档
非常重要,必须参考。
https://www.varnish-cache.org/docs
官方示例 Example
https://www.varnish-cache.org/trac/wiki/VCLExamples
VCL2.x升级到3.0
https://www.varnish-cache.org/docs/3.0/installation/upgrade.html
WIKI
https://www.varnish-cache.org/trac/
drupal on Varnish
https://www.varnish-cache.org/trac/wiki/VarnishAndDrupal
http://www.drupal001.com/2011/12/varnish-drupal-basic/