在VCL中,有3个重要的数据结构:
1.req:请求目标,当varnish接收到一个请求,这是req object就被创建了,在vcl_recv中的大部分工作,都是在req object上展开的。
2.beresp:后端服务器返回的目标,它包含返回的头信息,在vcl_fetch中的大部分工作都是在beresp onject上开展的。
3.obj:被cache的目标,只读的目标被保存于内存中,obj.ttl的值可以修改,其他的只能读
由于子程序没有参数,子进程必须的信息通过全局变量来处理。
以下是到处都可用的变量:
- now:当前时间
下面的变量在backend申明中有效: - .host:一个backend的主机名或者IP地址
- .port:一个backend的服务名字或者端口号
下面的变量在处理请求时有效: - cient.ip:客户端IP
- cient.identity:客户的id,用在负载均衡的时候的client director
- server.hostname:server的主机名
- server.identity:server的身份,使用-i参数设置,如果-i参数没有传递给varnishd,server.identity将给varnishd实例设置名字。
- server.ip:客户端连接上socket,接收到的IP地址
- server.port:客户端连接上socket,接收到的端口号
- req.request:请求类型,例如“GET”,“HEAD”
- req.proto:客户端的HTTP协议
- req.url:请求的URL
- req.backend:使用哪个后端服务器为这个请求提供服务
- req.backend.healthy:后端服务器是否健康
- req.http.具体header名字:对应的HTTP头,如req.http.Cookie
- req.hash_always_miss:强制本请求的缓存失效
- req.hash_ignore_busy:当lookup缓存时,忽略busy的对象
- req.can_gzip:设置能使用gzip
- req.restarts:设置最大的重启次数
- req.esi:设置是否支持ESI,今后会改变,建议不要使用
- req.esi_level:设置ESI的level
- req.grace:设置对象被保持的时间
- req.xid:请求的唯一id
下面这些变量在访问后端服务器的时候用
- bereq.request:请求的类型(如“GET”,“HEAD”)
- bereq.url:请求的url
- bereq.proto:请求的协议
- bereq.http.具体header名字:请求的HTTP头,如bereq.http.Cookie
- bereq.connect_timeout:等待后端服务器响应的时间
- bereq.first_byte_timeout:等待接受第一个字节的等待时间,pipe模式中无效
- bereq.between_bytes_timeout:两次从后端服务器接收到的字节的间隔,pipe模式无效
下面这些变量在从后端服务器取回,但还没有进入缓存的时候使用,也就是vcl_fetch变量
- beresp.do_stream:对象直接返回给客户端,不会再varnish中缓存。在Varnish3里面这些对象会被标记为busy
- beresp.do_esi:是否进行ESI处理
- beresp.do_gzip:是否存储前Gzip压缩
- beresp.do_gunzip:是否在存储前解压缩
- beresp.http.具体header名字:HTTP头部,如bereq.http.Cookie
- beresp.proto:HTTP协议
- beresp.status:HTTP的状态码
- beresp.response:服务端返回的状态消息
- beresp.ttl:对象保存的时间
- beresp.grace:对象grace保存的时间
- beresp.saintmode:saint模式持续的时间
- beresp.backend.name:response的backend的名字
- beresp.backend.ip:response的backend的ip
- beresp.backend.port:response的backend的端口
- beresp.storage:强制Varnish保存这个对象
下面这些变量在请求目标被成功的从后端服务器或者缓存中获得后有效
- obj.proto:返回请求目标的HTTP版本
- obj.status :服务器返回的HTTP状态码
- obj.response :服务器返回的HTTP状态信息
- obj.ttl:目标的剩余生存时间,以秒为单位。
- obj.lastuse:最后一个请求后,过去的时间,以秒为单位。
- obj.hits:大概的delivered的次数,如果为0,表明缓存出错。
- obj.grace:对象grace的存活时间
- obj.http.具体header的名字:Http header
下面这些变量在目标hash key以后有效
- req.hash:hashkey 和缓存中的目标相关,在读出和写入缓存时使用。
- 下面这些变量在准备回应客户端时使用
- resp.proto:准备响应的HTTP协议版本
- resp.status:返回客户端的HTTP状态码
- resp.response:返回客户端的HTTP状态信息
- resp.http.header:通信的HTTP头
使用SET关键字,把值分配给变量:
sub vcl_recv {
# Normalize the Host: header
if (req.http.host ~ "^(www.)?example.com$") {
set req.http.host = "www.example.com";
}
}
可以使用remove关键字把HTTP头彻底的删除:
sub vcl_fetch {
remove obj.http.Set-Cookie;
}
常见VCL应用片段
1.为不同的设备设置不同的header参数:
sub vcl_recv {
if (req.http.User-Agent ~ "iPad" ||
req.http.User-Agent ~ "iPhone" ||
req.http.User-Agent ~ "Android") {
set req.http.X-Device = "mobile";
} else {
set req.http.X-Device = "desktop";
}
}
2.想要取消访问/images的request的cookie:
sub vcl_recv {
if (req.url ~ "^/images") {
unset req.http.cookie;
}
}
3.通过ACL来控制能访问的ip地址
acl local {
"localhost";
"192.168.1.0"/24; /* and everyone on the local network */
! "192.168.1.23"; /* except for the dialin router */
}
sub vcl_recv {
if (req.request == "PURGE") {
if (client.ip ~ local) {
return(lookup);
}
}
}
sub vcl_hit {
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
error 404 "Not in cache.";
}
}
4.修改从后台服务器返回的对象的ttl:
sub vcl_fetch {
if (req.url ~ "\.(png|gif|jpg)$") {
unset beresp.http.set-cookie;
set beresp.ttl = 1h;
}
}
5.设置客户端发送的accept-encoding头只有gzip和deflate两种编码,gzip优先
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
# No point in compressing these
remove req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
# unknown algorithm
remove req.http.Accept-Encoding;
}
}
6.简单的图片防盗链:
if (req.http.referer ~ "http://.*") {
if ( !(req.http.referer ~ "http://.*baidu\.com"
|| req.http.referer ~ "http://.*google\.com"
|| req.http.referer ~ "http://.*google\.cn"
)) {
set req.http.host = "www.baidu.com";
set req.url = "/static/images/logo.gif";
}
return (lookup);
}