共计 13216 个字符,预计需要花费 34 分钟才能阅读完成。
目录
一、介绍
二、安装
RPM 安装
编译安装
安装依赖包
安装 pcre
编译
三、VCL 执行过程
四、通过日志调优
五、负载均衡
六、优雅模式和神圣模式
Grace mode
Saint mode
七、完整示例
八、管理命令
varnishncsa(以 NCSA 的格式显示日志)
varnishlog(varnish 详细日志)
varnishtop
varnishstat
varnishadm
最近公司做活动推广,流量暴增,后端服务器压力很大,导致用户的请求响应时间延长,客户因此抱怨声音很大。
为尽快解决问题,在安排人员不断优化后端代码的同时,考虑在 nginx 前增加 varnish 缓存层,只透传部分动态请求过去,直接减少后端服务器的压力。
在实际使用中,真正感受到了 varnish 服务器强大的威力!在不断的调优缓存命中率后,后端服务器 cpu 直接从 80% 降到了 20%,再大的压力前端也可以直接消化,后端服务器表示毫无压力。有了这玩意,可以再也不用在后台写定时任务,不断重新生成静态页面了,直接丢缓存里完事!此外,varnish 还支持一种叫“神圣模式”,在后端服务器报错返回 500 的时候,varnish 还能继续优先返回过去缓存的内容,为用户屏蔽部分错误,这东东有时真算是救命稻草啊。
但同时,也趟了 n 多的坑,varnish 中的 VCL 语言太过强大和灵活,稍微运用不好就会中枪。而网上公开的大多数 varnish 配置文件都是一大抄,根本无法直接用于生产。在研究了几天,翻阅了大量各种资料后,才总算把遇到的问题都解决了。
现将调优心得记录如下:
一、介绍
Varnish 是一种专业的网站缓存软件(其实就是带缓存的反向代理服务),它可以把整个 HTTP 响应内容缓存到内存或文件中,从而提高 Web 服务器的响应速度。
Varnish 内置强大的 VCL(Varnish Configuration Language)配置语言,允许通过各种条件判断来灵活调整缓存策略。在程序启动时,varnish 就把 VCL 转换成二进制代码,因此性能非常高。
二、安装
epel 源里也有 varnish,但是却 2.x 版本的。
因为 varnish 3.0 的配置文件与 2.x 的存在很大不同,因此 varnish 团队不能再更新 epel 里的软件源。如果你想安装最新版本,推荐使用 rpm 方式。
RPM 安装
在 RedHat 系服务器上可以很容易的直接通过 rpm 包安装:
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-libs-3.0.4-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-3.0.4-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-docs-3.0.4-1.el6.x86_64.rpm
yum localinstall *.rpm
varnish 的安装和配置路径
/etc/varnish/default.vcl #默认配置文件存文件
/etc/sysconfig/varnish #服务启动参数脚本
/etc/init.d/varnish #服务控制脚本
可以通过调整 /etc/sysconfig/varnish 配置文件中的参数来调整启动参数,设置线程池、缓存到内存还是文件等。当然如果你乐意也可以在 varnishd 后面带上启动参数手工启动服务和管理。
现在可以通过服务的方式启动 varnish 了:
service varnish start (stop/restart)
将 varnish 设为开机自启动:
chkconfig varnish on
编译安装
安装依赖包
yum install ncurses-devel.x86_64
此步可选。
如果你在编译 varnish 后 bin 目录中没有发现 varnishstat、varnishtop、varnishhist 这三个程序的话,就是因为编译前没有安装与操作系统位数对应的 ncurses-devel。这些工具非常好用,因此建议先安装这个依赖包。
安装 pcre
varnish 依赖 pcre 进行 url 正则匹配。
cd pcre-8.12
./configure –prefix=/usr/local/
make&&make install
编译
解压缩 varnish 源码包
wget http://repo.varnish-cache.org/source/varnish-3.0.4.tar.gz
cd /root
tar -zxvf varnish-3.0.4.tar.gz
cd varnish-3.0.4
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
./configure –prefix=/usr/local/varnish
make && make install
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2013-11/93119p2.htm
Varnish 的详细介绍:请点这里
Varnish 的下载地址:请点这里
相关阅读:
Varnish Cache 的架构笔记 http://www.linuxidc.com/Linux/2013-10/91016.htm
CentOS 5.8 下 Varnish-2.1.5 的安装配置 http://www.linuxidc.com/Linux/2013-09/89916.htm
RedHat 脚本改用 CentOS 源更新安装 Nginx、PHP 5.3、Varnish http://www.linuxidc.com/Linux/2012-07/65801.htm
利用 Varnish 构建 Cache 服务器笔记 http://www.linuxidc.com/Linux/2012-07/65234.htm
缓存服务 Varnish 安装配置 http://www.linuxidc.com/Linux/2012-07/65228.htm
Varnish 编译安装所需准备 http://www.linuxidc.com/Linux/2012-07/65230.htm
Linux 下 Varnish 缓存的配置优化 http://www.linuxidc.com/Linux/2012-03/56435.htm
Varnish 权威指南(中文)PDF http://www.linuxidc.com/Linux/2013-10/91021.htm
三、VCL 执行过程
先介绍一下 Varnish 处理请求的主要处理方法和流程
VCL 需定义几个默认的函数,在 Varnish 处理 HTTP 请求的各个阶段会回调这些函数进行处理:
- vcl_recv,请求入口,判断是否要进一步处理,还是直接转发给后端(pass)。此过程中可以使用和请求相关的变量,例如客户端请求的 url,ip,user-agent,cookie 等,此过程中可以把不需缓存的地址,通过判断(相等、不相等、正则匹配等方法)透传给后端,例如 POST 请求,及 jsp、asp、do 等扩展名的动态内容;
- vcl_fetch,当从后端服务器获取内容后会进入此阶段,除了可以使用客户端的请求变量,还可以使用从后端获取的信息(bersp),如后端返回的头信息,具体指定此信息的缓存时间 TTL;
- vcl_miss 缓存未命中时中要做的处理
- vcl_hit 缓存命中后做的处理
- vcl_delever 发送给客户端前的处理
- vcl_pass 交给后端服务器
- vcl_hash 设置缓存的键值 key
首次请求时过程如下:
recv->hash->miss->fetch->deliver
缓存后再次请求:
recv->hash->hit->deliver(fetch 的过程没了,这就是我们要做的,把要缓存的页面保存下来)
直接交给后端 pass 的情况:
recv->hash->pass->fetch->deliver(直接从后端获取数据后发送给客户端,此时 Varnish 相当于一个中转站,只负责转发)
四、通过日志调优
安装完成后,默认的配置文件位于
/etc/varnish/default.vcl
我们可以参考缺省配置项学习 vcl 语言的使用,并进行不断的调优。
但直接修改配置,不断的重启调优效率非常低下痛苦!经过不断摸索,我发现其实 varnish 里内置了日志模块,我们可以在 defalut.vcl 最上边引用 std 库,以便输出日志:
import std;
在需要输出日志的地方,使用 std.log 即可:
std.log(“LOG_DEBUG: URL=” + req.url);
这样的话,就可以通过日志了解 varnish 的工作流程,很方便的优化啦,效率何止提高十倍!
类似于你想跟踪哪些连接没有命中缓存,可以在 vcl_miss 函数中这样写:
sub vcl_miss {
td.log(“url miss!!! url=” + req.url);
return (fetch);
}
启动 varnish 后,通过 varnishlog 工具跟踪打印出的日志
varnishlog -I LOG
五、负载均衡
Varnish 可以挂载多个后端服务器,并进行权重、轮询,将请求转发到后端节点上,以达到避免单点的问题。
举例如下:
backend web1 {
.host = “172.16.2.31”;
.port = “80”;
.probe = {
.url = “/”;
.interval = 10s;
.timeout = 2s;
.window = 3;
.threshold = 3;
}
}
backend web2 {
.host = “172.16.2.32”;
.port = “80”;
.probe = {
.url = “/”;
.interval = 10s;
.timeout = 2s;
.window = 3;
.threshold = 3;
}
}
# 定义负载均衡组
director webgroup random {
{
.backend = web1;
.weight = 1;
}
{
.backend = web2;
.weight = 1;
}
}
其中,在 backend 中添加 probe 选项,将可以对后端节点进行健康检查。如果后端节点无法访问,将会自动摘除掉该节点,直到这个节点恢复。
需要注意 window 和 threshold 两个参数。当有后端服务器不可达时,varnish 会时不时的报 503 错误。网上查出的资料都是改线程组什么的,经测试完全无效。后来发现,只要将 window 和 threshold 两个参数的值设成一样的,503 现象就再没有发生了。
目录
一、介绍
二、安装
RPM 安装
编译安装
安装依赖包
安装 pcre
编译
三、VCL 执行过程
四、通过日志调优
五、负载均衡
六、优雅模式和神圣模式
Grace mode
Saint mode
七、完整示例
八、管理命令
varnishncsa(以 NCSA 的格式显示日志)
varnishlog(varnish 详细日志)
varnishtop
varnishstat
varnishadm
最近公司做活动推广,流量暴增,后端服务器压力很大,导致用户的请求响应时间延长,客户因此抱怨声音很大。
为尽快解决问题,在安排人员不断优化后端代码的同时,考虑在 nginx 前增加 varnish 缓存层,只透传部分动态请求过去,直接减少后端服务器的压力。
在实际使用中,真正感受到了 varnish 服务器强大的威力!在不断的调优缓存命中率后,后端服务器 cpu 直接从 80% 降到了 20%,再大的压力前端也可以直接消化,后端服务器表示毫无压力。有了这玩意,可以再也不用在后台写定时任务,不断重新生成静态页面了,直接丢缓存里完事!此外,varnish 还支持一种叫“神圣模式”,在后端服务器报错返回 500 的时候,varnish 还能继续优先返回过去缓存的内容,为用户屏蔽部分错误,这东东有时真算是救命稻草啊。
但同时,也趟了 n 多的坑,varnish 中的 VCL 语言太过强大和灵活,稍微运用不好就会中枪。而网上公开的大多数 varnish 配置文件都是一大抄,根本无法直接用于生产。在研究了几天,翻阅了大量各种资料后,才总算把遇到的问题都解决了。
现将调优心得记录如下:
一、介绍
Varnish 是一种专业的网站缓存软件(其实就是带缓存的反向代理服务),它可以把整个 HTTP 响应内容缓存到内存或文件中,从而提高 Web 服务器的响应速度。
Varnish 内置强大的 VCL(Varnish Configuration Language)配置语言,允许通过各种条件判断来灵活调整缓存策略。在程序启动时,varnish 就把 VCL 转换成二进制代码,因此性能非常高。
二、安装
epel 源里也有 varnish,但是却 2.x 版本的。
因为 varnish 3.0 的配置文件与 2.x 的存在很大不同,因此 varnish 团队不能再更新 epel 里的软件源。如果你想安装最新版本,推荐使用 rpm 方式。
RPM 安装
在 RedHat 系服务器上可以很容易的直接通过 rpm 包安装:
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-libs-3.0.4-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-3.0.4-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-docs-3.0.4-1.el6.x86_64.rpm
yum localinstall *.rpm
varnish 的安装和配置路径
/etc/varnish/default.vcl #默认配置文件存文件
/etc/sysconfig/varnish #服务启动参数脚本
/etc/init.d/varnish #服务控制脚本
可以通过调整 /etc/sysconfig/varnish 配置文件中的参数来调整启动参数,设置线程池、缓存到内存还是文件等。当然如果你乐意也可以在 varnishd 后面带上启动参数手工启动服务和管理。
现在可以通过服务的方式启动 varnish 了:
service varnish start (stop/restart)
将 varnish 设为开机自启动:
chkconfig varnish on
编译安装
安装依赖包
yum install ncurses-devel.x86_64
此步可选。
如果你在编译 varnish 后 bin 目录中没有发现 varnishstat、varnishtop、varnishhist 这三个程序的话,就是因为编译前没有安装与操作系统位数对应的 ncurses-devel。这些工具非常好用,因此建议先安装这个依赖包。
安装 pcre
varnish 依赖 pcre 进行 url 正则匹配。
cd pcre-8.12
./configure –prefix=/usr/local/
make&&make install
编译
解压缩 varnish 源码包
wget http://repo.varnish-cache.org/source/varnish-3.0.4.tar.gz
cd /root
tar -zxvf varnish-3.0.4.tar.gz
cd varnish-3.0.4
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
./configure –prefix=/usr/local/varnish
make && make install
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2013-11/93119p2.htm
Varnish 的详细介绍:请点这里
Varnish 的下载地址:请点这里
相关阅读:
Varnish Cache 的架构笔记 http://www.linuxidc.com/Linux/2013-10/91016.htm
CentOS 5.8 下 Varnish-2.1.5 的安装配置 http://www.linuxidc.com/Linux/2013-09/89916.htm
RedHat 脚本改用 CentOS 源更新安装 Nginx、PHP 5.3、Varnish http://www.linuxidc.com/Linux/2012-07/65801.htm
利用 Varnish 构建 Cache 服务器笔记 http://www.linuxidc.com/Linux/2012-07/65234.htm
缓存服务 Varnish 安装配置 http://www.linuxidc.com/Linux/2012-07/65228.htm
Varnish 编译安装所需准备 http://www.linuxidc.com/Linux/2012-07/65230.htm
Linux 下 Varnish 缓存的配置优化 http://www.linuxidc.com/Linux/2012-03/56435.htm
Varnish 权威指南(中文)PDF http://www.linuxidc.com/Linux/2013-10/91021.htm
六、优雅模式和神圣模式
Grace mode
如果后端需要很长时间来生成一个对象,这里有一个线程堆积的风险。为了避免这 种情况,你可以使用 Grace。他可以让 varnish 提供一个存在的版本,然后从后端生成新 的目标版本。当同时有多个请求过来的时候,varnish 只发送一个请求到后端服务器,在
set beresp.grace = 30m;
时间内复制旧的请求结果给客户端。
Saint mode
有时候, 服务器很古怪, 他们发出随机错误, 您需要通知 varnish 使用更加优雅的方式处理 它, 这种方式叫神圣模式(saint mode)。Saint mode 允许您抛弃一个后端服务器或者另一个尝试的后端服务器或者 cache 中服务陈旧的内容。
例如:
sub vcl_fetch {
if (beresp.status == 500) {
set beresp.saintmode = 10s;
return (restart);
}
set beresp.grace = 5m;
}
七、完整示例
import std;
backend web1 {
.host = “172.16.2.31”;
.port = “80”;
.probe = {
.url = “/”;
.interval = 10s;
.timeout = 2s;
.window = 3;
.threshold = 3;
}
}
backend web2 {
.host = “172.16.2.32”;
.port = “80”;
.probe = {
.url = “/”;
.interval = 10s;
.timeout = 2s;
.window = 3;
.threshold = 3;
}
}
# 定义负载均衡组
director webgroup random {
{
.backend = web1;
.weight = 1;
}
{
.backend = web2;
.weight = 1;
}
}
# 允许刷新缓存的 ip
acl purgeAllow {
“localhost”;
“172.16.2.5”;
}
sub vcl_recv {
# 刷新缓存设置
if (req.request == “PURGE”) {
#判断是否允许 ip
if (!client.ip ~ purgeAllow) {
error 405 “Not allowed.”;
}
#去缓存中查找
return (lookup);
}
std.log(“LOG_DEBUG: URL=” + req.url);
set req.backend = webgroup;
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 请求
if (req.request != “GET” && req.request != “HEAD”) {
std.log(“LOG_DEBUG: req.request not get! ” + req.request);
return(pass);
}
# http 认证的页面也 pass
if (req.http.Authorization) {
std.log(“LOG_DEBUG: req is authorization !”);
return (pass);
}
if (req.http.Cache-Control ~ “no-cache”) {
std.log(“LOG_DEBUG: req is no-cache”);
return (pass);
}
# 忽略 admin、verify、servlet 目录,以.jsp 和.do 结尾以及带有? 的 URL, 直接从后端服务器读取内容
if (req.url ~ “^/admin” || req.url ~ “^/verify/” || req.url ~ “^/servlet/” || req.url ~ “\.(jsp|php|do)($|\?)”) {
std.log(“url is admin or servlet or jsp|php|do, pass.”);
return (pass);
}
# 只缓存指定扩展名的请求, 并去除 cookie
if (req.url ~ “^/[^?]+\.(jpeg|jpg|png|gif|bmp|tif|tiff|ico|wmf|js|css|ejs|swf|txt|zip|exe|html|htm)(\?.*|)$”) {
std.log(“*** url is jpeg|jpg|png|gif|ico|js|css|txt|zip|exe|html|htm set cached! ***”);
unset req.http.cookie;
# 规范请求头,Accept-Encoding 只保留必要的内容
if (req.http.Accept-Encoding) {
if (req.url ~ “\.(jpg|png|gif|jpeg)(\?.*|)$”) {
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 {
remove req.http.Accept-Encoding;
}
}
return(lookup);
} else {
std.log(“url is not cached!”);
return (pass);
}
}
sub vcl_hit {
if (req.request == “PURGE”) {
set obj.ttl = 0s;
error 200 “Purged.”;
}
return (deliver);
}
sub vcl_miss {
std.log(“################# cache miss ################### url=” + req.url);
if (req.request == “PURGE”) {
purge;
error 200 “Purged.”;
}
}
sub vcl_fetch {
# 如果后端服务器返回错误,则进入 saintmode
if (beresp.status == 500 || beresp.status == 501 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) {
std.log(“beresp.status error!!! beresp.status=” + beresp.status);
set req.http.host = “status”;
set beresp.saintmode = 20s;
return (restart);
}
# 如果后端静止缓存, 则跳过
if (beresp.http.Pragma ~ “no-cache” || beresp.http.Cache-Control ~ “no-cache” || beresp.http.Cache-Control ~ “private”) {
std.log(“not allow cached! beresp.http.Cache-Control=” + beresp.http.Cache-Control);
return (hit_for_pass);
}
if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == “*”) {
/* Mark as “Hit-For-Pass” for the next 2 minutes */
set beresp.ttl = 120 s;
return (hit_for_pass);
}
if (req.request == “GET” && req.url ~ “\.(css|js|ejs|html|htm)$”) {
std.log(“gzip is enable.”);
set beresp.do_gzip = true;
set beresp.ttl = 20s;
}
if (req.request == “GET” && req.url ~ “^/[^?]+\.(jpeg|jpg|png|gif|bmp|tif|tiff|ico|wmf|js|css|ejs|swf|txt|zip|exe)(\?.*|)$”) {
std.log(“url css|js|gif|jpg|jpeg|bmp|png|tiff|tif|ico|swf|exe|zip|bmp|wmf is cache 5m!”);
set beresp.ttl = 5m;
} elseif (req.request == “GET” && req.url ~ “\.(html|htm)$”) {
set beresp.ttl = 30s;
} else {
return (hit_for_pass);
}
# 如果后端不健康,则先返回缓存数据 1 分钟
if (!req.backend.healthy) {
std.log(“eq.backend not healthy! req.grace = 1m”);
set req.grace = 1m;
} else {
set req.grace = 30s;
}
return (deliver);
}
# 发送给客户端
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = “has cache”;
} else {
#set resp.http.X-Cache = “no cache”;
}
return (deliver);
}
八、管理命令
跟随 varnish 会一起安装一些方便的调试工具,用好这些工具,对你更好的应用 varnish 有很大的帮助。
varnishncsa(以 NCSA 的格式显示日志)
通过这个命令,可以像类似于 nginx/apache 一样的显示出用户的访问日志来。
varnishlog(varnish 详细日志)
如果你想跟踪 varnish 处理每个请求时的详细处理情况,可以使用此命令。
直接使用这个命令,显示的内容非常多,通常我们可以通过一些参数,使它只显示我们关心的内容。
- -b \\ 只显示 varnish 和 backend server 之间的日志,当您想要优化命中率的时 候可以使用这个参数。
- -c \\ 和 - b 差不多,不过它代表的是 varnish 和 client 端的通信。
- -i tag \\ 只显示某个 tag,比如“varnishlog –i SessionOpen”将只显示新会话,注 意,这个地方的 tag 名字是不区分大小写的。
- -I \\ 通过正则表达式过滤数据,比如“varnishlog -c -i RxHeader -I Cookie”将 显示所有接到到来自客户端的包含 Cookie 单词的头信息。
- -o \\ 聚合日志请求 ID
例如:
varnishlog -c -o /auth/login 这个命令将告诉您来自客户端(-c)的所有包含”/auth/login”字段(-o)请求。
varnishlog -c -o ReqStart 192.168.1.100 只跟踪一个单独的 client 请求
varnishtop
您可以使用 varnishtop 确定哪些 URL 经常被透传到后端。
适当的过滤使用 –I,-i,-X 和 -x 选项,它可以按照您的要求显示请求的内容,客
户端,浏览器等其他日志里的信息。
varnishtop -i rxurl \\ 您可以看到客户端请求的 url 次数。
Varnishtop -i txurl \\ 您可以看到请求后端服务器的 url 次数。
Varnishtop -i Rxheader -I Accept-Encoding \\ 可以看见接收到的头信息中有有多少次
包含 Accept-Encoding。
varnishstat
显示一个运行 varnishd 实例的相关统计数据。
Varnish 包含很多计数器,请求丢失率,命中率,存储信息,创建线程,删除对象等,几乎所有的操作。通过跟踪这些计数器,可以很好的了解 varnish 运行状态。
varnishadm
通过命令行,控制 varnish 服务器。可以动态的删除缓存,重新加载配置文件等。
管理端口有两种链接方式:
1,telnet 方式, 可以通过 telnet 来连接管理端口. 如:”telnet localhost 6082″
2,varnishadm 方式, 可以通过 varnish 自带的管理程序传递命令. 如: varnishadm -n vcache -T localhost:6082 help
动态清除缓存
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 ban.url /2011111.png
其中:ban.url 后的路径一定不要带 abc.xxx.com 域名之类的,否则缓存清除不了。
清除包含某个子目录的 URL 地址:
/usr/local/varnish/bin/varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 url.purge /a/
不重启加载配置文件
登陆到管理界面
/usr/local/varnish/bin/varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
加载配置文件
vcl.load new.vcl /etc/varnish/default.vcl
编译出错的话会有提示,成功会返回 200
加载新配置文件
vcl.use new.vcl
此时新的配置文件已经生效!