一次客户端请求过程:
客户端请求----》浏览器缓存------》公共缓存------》后端服务器。
vrnish的状态引擎(state engine)
vcl_recv:刚收到请求
vcl_fetch:去后端服务器取内容
vcl_deliver:投递响应报文
vcl_hit:命中
vcl_miss:没命中
vcl_hash:因为varnish采用的是范域名解析,通过vcl_hash可以确定不同的key对应的是否为同一值。
vcl_pipe:如果客户端请求的方法不是一个正常的方法(不是GET,HEAD,PUT,POST,TRACE,OPTIONS,DELECT),或者varnish不能理解这个方法,则有vcl_pipe引擎直接将请求扔给后端主机。
vcl_error:由varnish直接合成一个错误页面信息返回给客户端。
vcl_pass:请求的是一个不可缓存的对象,但varnish能理解请求(例如:请求的方法不是GET和HEAD,或请求带cookie、带认证等)
【注意】:各状态引擎之间存在一定的相关性,不能随意指定顺寻,且前一个engine可能有多个不同的下游engine,则上游engine需要用return指明需要转移的下游engine
vcl编程语言语法:
(1)//,#,/\*...*/ 用于注释;
(2)sub $name #用于定义子例程
sub vcl_recv{
}
(3)不支持循环
(4)有众多内置变量,变量的可调用位置与state engine有密切相关性;
(5)支持终止语句;return(action);没有返回值
(6)"域"专用
(7)操作符:=,==,~,!,&&,||
条件判断语句:
if (CONDTION) {
} else {
}
变量赋值:set name=value ,unset name
req.http.HEADER:调用request报文中http协议的指定HEADER;
req.http.X-forwarded-for
req.http.Auhtorization
req.http.cookie
req.request:请求方法
client.ip:客户端ip
beresp :后端响应报文
state engine workflow(Version 3):
vcl_recv---->vcl_hash---->vcl_hit---->vcl_deliver
vcl_recv---->vcl_hash---->vcl_miss---->vcl_fetch---->vcl_deliver
vcl_recv---->vcl_pass---->vcl_fetch---->vcl_deliver
vcl_revc---->pipe
state engine(V 4)
vcl_recv,vcl_hash,vcl_hit,vcl_miss,vcl_pipe,vcl_pass
vcl_backend_fetch
vcl_backend_response
vcl_backend_error
vcl_purge
vcl_synth
varnish中的内置变量:
变量种类:
req:客户端发往varnish的requesrt
resp:varnnish响应给客户端
client:
server
server.ip
server.hostname
bereq:varnish发给后端主机的
bereq.http.HEADERS:由varnish发往backend server的请求报文的指定首部
bereq.request:请求方法
bereq.backend:指明要调用的后端主机
beresp:后端主机响应给varnish的
beresp.http.HEADER:从backend server响应的报文首部
obj:内容的属性
obj-ttl:对象的ttl值
obj-hits:此对象从缓存中命中的次数
storage
接下来我们尝试重新编译vcl文件,并将其应用于我们的服务。
cp /etc/varnish/default.vcl /etc/varnish/test.vcl
在varnish官网(http://book.varnish-software.com/4.0/chapters/VCL_Basics.html) 上复制vcl_recv的内容
[root@server7 ~]# vim /etc/varnish/test.vcl
sub vcl_recv {
if (req.method == "PRI") {
/* We do not support SPDY or HTTP/2.0 */
return (synth(405));
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.method != "GET" && req.method != "HEAD") {
/* 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 (hash);
}
sub vcl_deliver {
#对于obj.hits文件来说,第一次从缓存中取值,则obj.hits=1,第二次为2,第三次为3....
if (obj.hits>0) {
set resp.http.X-Cache = "Hit";
}
else {
set resp.http.X-cache = "Miss";
}
}
使用varnishadm工具连上去
[root@server7 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
vcl.load test2 test.vcl #装载vcl文件
vcl.use test2 #使用vcl文件
去请求6081端口,因为之前已经请求过该页面了,所以可以看到X-Cache的值为Hit
我们去请求一个没有访问过的页面
这时,第一次请求该页面的值为Miss,第二次为Hit
我们也可以自定义一些后端主机,例如我们可以自定义一个后端的图片服务器。
backend imgsrv {
.host = "172.25.44.9";
.port = "80";
}
.host :BE的地址
.port:BE监听的端口
.probe :对BE做健康状态检测
.max_connections :最大连接数
让varnish支持虚拟主机
vcl_recv 部分:
if(req.http.host == “www.wtt.com“ ) {
}
强制对某资源的请求不检查缓存
if (req.url ~ "^/test1.html$")
{
return(pass);
}
每一修改完vcl文件后都要重新的装载使用
vcl.load test3 test.vcl
200
VCL compiled.
vcl.use test3
200
VCL 'test3' now active
这时后去访问test1.html式一直都是Miss状态,表示结果没有从缓存服务器返回
后端主机的健康状态检测方式:
probe name {
.attribute = "value"
}
.url :判断BE健康与否要请求的URL
.expected_responce:期望响应的状态码,默认为200
负载均衡算法:
fallback,random,round_robin,hash