简介
Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的 squid 相比,varnish 具有性能更高、速度更快、管理更加方便等诸多优点;
目前最新版本是4.0.0,而3.x的版本也是可以生产环境下使用的稳定版本,但yum源中的2.x版本过于陈旧,不建议使用;
Varnish与Squid的对比
相同点
Varnish的优势
Varnish的劣势
Varnish劣势的解决方案
对比Varnish 3.x的主要改进
涉及VCL语法的改变点
详见:https://www.varnish-cache.org/docs/4.0/whats-new/index.html#whats-new-index
架构及文件缓存的工作流程
Child 进程分配若干线程进行工作,主要包括一些管理线程和很多 worker 线程,可分为:
HTTP请求基本处理流程
Varnish 处理 HTTP 请求的过程如下
注:Varnish4中在vcl_fetch部分略有出入,已独立为vcl_backend_fetch和vcl_backend_response2个函数;
内置函数(也叫子例程)
VCL中内置公共变量
变量(也叫object)适用范围
注:某些地方略有出入,详细可参考官方文档;
变量类型详解
具体变量详见:https://www.varnish-cache.org/docs/4.0/reference/vcl.html#reference-vcl
优雅模式(Garce mode)
Varnish中的请求合并
当几个客户端请求同一个页面的时候,varnish只发送一个请求到后端服务器,然后让其他几个请求挂起并等待返回结果;获得结果后,其它请求再复制后端的结果发送给客户端;
但如果同时有数以千计的请求,那么这个等待队列将变得庞大,这将导致2类潜在问题:
故为了解决这类问题,可以配置varnish在缓存对象因超时失效后再保留一段时间,以给那些等待的请求返回过去的文件内容(stale content),配置案例如下:
sub vcl_recv {if (! req.backend.healthy) {
set req.grace = 5m;
} else {
set req.grace = 15s;
}
}
sub vcl_fetch {
set beresp.grace = 30m;
}
# 以上配置表示varnish将会将失效的缓存对象再多保留30分钟,此值等于最大的req.grace值即可;
# 而根据后端主机的健康状况,varnish可向前端请求分别提供5分钟内或15秒内的过期内容
安装配置
# 安装包下载地址:http://repo.varnish-cache.org/redhat/varnish-4.0/el6/yum localinstall --nogpgcheck varnish-4.0.0-1.el6.x86_64.rpm varnish-libs-4.0.0-1.el6.x86_64.rpm varnish-docs-4.0.0-1.el6.x86_64.rpmvi /etc/sysconfig/varnish # 编辑配置文件,修改如下项
VARNISH_STORAGE_SIZE=100M # 此值根据自身情况调整,测试环境可调低此值
VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}" # Varnish 4中默认使用malloc(即内存)作为缓存对象存储方式;
service varnish start # 启动varnish,默认外部请求的监听端口6081,管理端口6082,后端主机127.0.0.1:80===========varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 # 登录管理命令行
varnish> vcl.list # 列出所有的配置
varnish> vcl.load test1 test.vcl # 加载编译新配置,test1是配置名,test.vcl是配置文件
varnish> vcl.use test1 # 使用配置,需指定配置名,当前使用的配置以最后一次vcl.use为准
varnish> vcl.show test1 # 显示配置内容,需指定配置名
实例解析
#
# This is an example VCL file for Varnish.
#
# It does not do anything by default, delegating control to the
# builtin VCL. The builtin VCL is called when there is no explicit
# return statement.
#
# See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/# and http://varnish-cache.org/trac/wiki/VCLExamples for more examples.# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;
import directors;
probe backend_healthcheck { # 创建健康监测
.url = /health.html;
.window = 5;
.threshold = 2;
.interval = 3s;
}
backend web1 { # 创建后端主机
.host = "static1.lnmmp.com";
.port = "80";
.probe = backend_healthcheck;
}
backend web2 {
.host = "static2.lnmmp.com";
.port = "80";
.probe = backend_healthcheck;
}
backend img1 {
.host = "img1.lnmmp.com";
.port = "80";
.probe = backend_healthcheck;
}
backend img2 {
.host = "img2.lnmmp.com";
.port = "80";
.probe = backend_healthcheck;
}
vcl_init { # 创建后端主机组,即directors
new web_cluster = directors.random();
web_cluster.add_backend(web1);
web_cluster.add_backend(web2);
new img_cluster = directors.random();
img_cluster.add_backend(img1);
img_cluster.add_backend(img2);
}
acl purgers { # 定义可访问来源IP "127.0.0.1"; "192.168.0.0"/24;
}
sub vcl_recv { if (req.request == "GET" && req.http.cookie) { # 带cookie首部的GET请求也缓存
return(hash);
} if (req.url ~ "test.html") { # test.html文件禁止缓存
return(pass);
} if (req.request == "PURGE") { # PURGE请求的处理 if (!client.ip ~ purgers) {
return(synth(405,"Method 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 ~ "(?i)^(www.)?lnmmp.com$") { # 根据不同的访问域名,分发至不同的后端主机组
set req.http.host = "www.lnmmp.com";
set req.backend_hint = web_cluster.backend();
} elsif (req.http.host ~ "(?i)^images.lnmmp.com$") {
set req.backend_hint = img_cluster.backend();
}
return(hash);
}
sub vcl_hit { # PURGE请求的处理 if (req.request == "PURGE") {
purge;
return(synth(200,"Purged"));
}
}
sub vcl_miss { # PURGE请求的处理 if (req.request == "PURGE") {
purge;
return(synth(404,"Not in cache"));
}
}
sub vcl_pass { # PURGE请求的处理 if (req.request == "PURGE") {
return(synth(502,"PURGE on a passed object"));
}
}
sub vcl_backend_response { # 自定义缓存文件的缓存时长,即TTL值 if (req.url ~ "\.(jpg|jpeg|gif|png)$") {
set beresp.ttl = 7200s;
} if (req.url ~ "\.(html|css|js)$") {
set beresp.ttl = 1200s;
} if (beresp.http.Set-Cookie) { # 定义带Set-Cookie首部的后端响应不缓存,直接返回给客户端
return(deliver);
}
}
sub vcl_deliver { if (obj.hits > 0) { # 为响应添加X-Cache首部,显示缓存是否命中
set resp.http.X-Cache = "HIT from " + server.ip;
} else {
set resp.http.X-Cache = "MISS";
}
}