Varnish Cache是一个web应用程序加速器,也是一个HTTP反向代理软件。放在HTTP服务器前端,
缓存内容。它采用“Visual Page Cache"技术,所有缓存数据直接从内存读取,因此速度非常快。
VCL4相比VCL3语法的改变点
要在配置文件中指定版本:即在第一行写上 vcl 4.0;
vcl_fetch函数被vcl_backend_response代替,且req.*不再适用vcl_backend_response;
后端源服务器组director成为varnish模块,需import directors后再在vcl_init子例程中定义;
vcl_error变更为vcl_backend_error,必须使用beresp.*,而不是obj.*。
req.request变更为req.method,obj为只读对象了。
自定义的子例程(即一个sub)不能以vcl_开头,调用使用call sub_name;
error()函数被synth()替代;
return(lookup)被return(hash)替代;
使用beresp.uncacheable创建hit_for_pss对象;
变量req.backend.healty被std.healthy(req.backend)替代;
变量req.backend被req.backend_hint替代;
关键字remove被unset替代;
关键字"purge;"命令,已被去除。在vcl_recv使用return(purge)。
vcl_synth采用resp.*,而非原来的obj.* 。
更详细改变,请查看官方文档。
https://www.varnish-cache.org/docs/4.0/whats-new/upgrading.html
VCL内置函数
vcl_recv 在一个请求到达时调用,它的决定是否处理此请求,以及如何处理。可使用以下几个终止语句:
synth(状态码,原因)
pass:绕过缓存,不从缓存中查询内容也不讲内容存至缓存中
pipe:不对客户端进行检查或做出任何操作,通过管道直接送往后方服务器,将数据直接通过管道在两者间传送
purge 清除此对象
hash 在缓存中查找用户请求的对象,如果缓存中没有其请求的对象,后续操作很可能会将其请求的对象进行缓存;
vcl_pipe 此函数在进入pipe模式时被调用,用于将请求直接传递至后端主机,并将后端响应原样返回客户端;
synth(satus code,reason)
pipe
vcl_pass 此函数在进入pass模式时被调用,用于将请求直接传递至后端主机,但后端主机的响应并不缓存直接返回客户端;
synth(status code,reason)
fetch 表示从后端获取请求的内容,并把控制权交给vcl_fetch函数。
restart 重启整个VCL,并增加重启计数;超出max_restarts限定的最大重启次数后将会返回错误信息;
vcl_hit 在执行 lookup 指令后,在缓存中找到请求的内容后将自动调用该函数;
restart
deliver 缓存此对象,并将其发送给客户端(经由vcl_deliver);
synth(status code,reason)
vcl_miss 在执行 lookup 指令后,在缓存中没有找到请求的内容时自动调用该方法,此函数可用于判断是否需要从后端服务器获取内容;
synth(status code,reason)
pass
fetch
restart
vcl_hash 在vcl_recv调用后为请求创建一个hash值时,调用此函数;此hash值将作为varnish中搜索缓存对象的key;
lookup 在缓存中查找用户请求的对象,并把控制权交给vcl_miss,vcl_hit或者vcl_purge
vcl_purge pruge操作执行后调用此函数,可用于构建一个响应;
synth
restart
vcl_deliver 将在缓存中找到请求的内容发送给客户端前调用此方法;
deliver
restart
vcl_backend_fetch 向后端主机发送请求前,调用此函数,可修改发往后端的请求;
fetch
abandon 放弃后端的请求,并生成一个错误
vcl_backend_response 获得后端主机的响应后,可调用此函数;
deliver
abandon
retry
vcl_backend_error 当从后端主机获取源文件失败时,调用此函数;
deliver
retry
vcl_synth
deliver
restart
vcl_init VCL加载时调用此函数,经常用于初始化varnish模块(VMODs)
ok 正常返回,VCL继续工作
vcl_fini 当所有请求都离开当前VCL,且当前VCL被弃用时,调用此函数,经常用于清理varnish模块;
ok
变量类型:
req:The request object,请求到达时可用的变量
bereq:The backend request object,向后端主机请求时可用的变量
beresp:The backend response object,从后端主机获取内容时可用的变量
resp:The HTTP response object,对客户端响应时可用的变量
obj:存储在内存中时对象属性相关的可用的变量
案例分析:
vcl 4.0; probe backend_healthcheck { #健康状况监测 .url = "/health.html"; .timeout = 1s; .interval = 10s; .window = 5; .threshold = 2; } backend web2 { #创建后端主机 .host = "192.168.1.139"; .port = "80"; .probe = backend_healthcheck; } backend p_w_picpath1 { .host = "192.168.1.140"; .port = "80"; .probe = backend_healthcheck; } backend p_w_picpath2 { .host = "192.168.1.141"; .port = "80"; .probe = backend_healthcheck; } backend web1 { .host = "192.168.1.138"; .port = "80"; .probe = backend_healthcheck; } import directors; sub vcl_init { #创建后端主机组,基于round_robin轮转 new web_cluster = directors.round_robin(); web_cluster.add_backend(web1); web_cluster.add_backend(web2); new img_cluster = directors.round_robin(); img_cluster.add_backend(p_w_picpath1); img_cluster.add_backend(p_w_picpath2); } acl purgers { #定义PURGE方法访问来源IP "localhost"; "127.0.0.1"; "192.168.1.0"/24; } sub vcl_recv { if (req.method == "GET" && req.http.Cookie) { #缓存带cookie的GET请求 return(hash); } if (req.url ~ "test.html") { #测试页面不缓存 return(pass); } if (req.method == "PURGE") { #当发送PURGE请求的客户端不再acl中指定地址时,返回405状态代码,并提示Not allowed. if (!client.ip ~ purgers) { return(synth(405,"Not allowed")); } return(hash); } if (req.http.X-Forward-For) { #为后端主机添加X-Forward-For首部 set req.http.X-Forward-For = req.http.X-Forward-For + "," +client.ip; } else { set req.http.X-Forward-For = client.ip; } if (req.http.host ~ "^(www.|bbs.)?mingxiao.info") { #域名访问策略 set req.backend_hint = web_cluster.backend(); } if (req.http.host ~ "^(img.|p_w_picpaths.)?mingxiao.info") { set req.backend_hint = img_cluster.backend(); } return(hash); } sub vcl_hit { #如果请求的是PURGE方法,命中的话返回200状态码。 if (req.method == "PURGE") { return(synth(200,"Purged")); } } sub vcl_miss { if (req.method == "PURGE") { return(synth(404,"Not in cache")); } } sub vcl_pass { if (req.method == "PURGE") { return(synth(502,"PURGE on a passed object")); } } sub vcl_backend_response { if (bereq.url ~ "\.(jpg|jpeg|gif|png)$") { set beresp.ttl = 6000s; } if (bereq.url ~ "\.(html|css|js)$") { set beresp.ttl = 6000s; } if (beresp.http.Set-Cookie) { return(deliver); } } sub vcl_deliver { if (obj.hits >0) { set resp.http.X-Cache="Hit from"+" "+server.ip; } else { set resp.http.X-Cache="Miss from"+" "+server.ip; } }