Varnish是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang (http://www.vg.no) 使用3台Varnish代替了原来的12台squid,性能居然比以前更好。
Varnish 的作者Poul-Henning Kamp是FreeBSD的内核开发者之一,他认为现在的计算机比起1975年已经复杂许多。在1975年时,储存媒介只有两种:内存与硬盘。但现在计算 机系统的内存除了主存外,还包括了cpu内的L1、L2,甚至有L3快取。硬盘上也有自己的快取装置,因此squid cache自行处理物件替换的架构不可能得知这些情况而做到最佳化,但操作系统可以得知这些情况,所以这部份的工作应该交给操作系统处理,这就是 Varnish cache设计架构。
具体安装方法
安装 CentOS 5.x 的Varnish RPM仓库
rpm --nosignature -i http://repo.varnish-cache.org/redhat/varnish-3.0/el5/noarch/varnish-release/varnish-release-3.0-1.el5.centos.noarch.rpm
安装 CentOS 6.x 的Varnish RPM仓库
rpm --nosignature -i http://repo.varnish-cache.org/redhat/varnish-3.0/el6/noarch/varnish-release/varnish-release-3.0-1.el6.noarch.rpm
然后执行安装完毕
yum install varnish
修改启动参数:
vim /etc/sysconfig/varnish
默认HTTP端口:6081
默认管理端口:6082
默认缓存模式为file:file,/var/lib/varnish/varnish_storage.bin,1G
共三种模式file, malloc, persistent
(1)file:使用特定的文件存储全部的缓存数据,并通过操作系统的mmap()系统调用将整个缓存文件映射至内存区域(如果条件允许);
(2)malloc:使用malloc()库调用在varnish启动时向操作系统申请指定大小的内存空间以存储缓存对象;
(3)persistent(experimental):与file的功能相同,但可以持久存储数据(即重启varnish数据时不会被清除);仍处于测试期;
修改varnish配置文件
vim /etc/varnish/default.vcl
VCL配置
############定义健康状态检测############### probe healthcheck { .url = "/"; #定义健康检查的页面 .interval = 6s; #探测请求的发送周期,默认为5秒; .timeout = 1s; #每次探测请求的过期时长 .window = 8; #设定在判定后端主机健康状态时基于最近多少次的探测进行 .threshold = 3; #在.window中指定的次数中,至少有多少次是成功的才判定后端主机正健康运行 .initial = 3; #Varnish启动时对后端主机至少需要多少次的成功探测,默认同.threshold } ############## app 服务器组及集群策略 ################ backend app01 { .host = "192.168.0.5"; .port = "80"; .probe = healthcheck; #健康状态检测 } backend app02 { .host = "192.168.0.6"; .port = "80"; .probe = healthcheck; #健康状态检测 } # 定义集群,调用服务器 director app random { #定义一个名为webserver的directory,由app01,app02,使用random算法,处理静态请求 {.backend = app01;.weight = 5;} #设置权重为 {.backend = app02;.weight = 5;} } ############## img 服务器 ################ backend img { .host = "192.168.0.1"; .port = "80"; } ####################################### #purge的acl规则 acl purge { "localhost"; "127.0.0.1"; } #vcl_recv函数段 sub vcl_recv { # varnish内部有一个grace模式。当后端不可用,或者已经向后端发过更新请求的情况下,别的客户再请求这个对象时,会收到已经过期的版本,当然过期的时间在可接受的范围内。 # 在收到用户请求时指定可以接受过期对象的过期时间范围 if (!req.backend.healthy) { set req.grace = 5m; } else { set req.grace = 15s; } #定义清除缓存IP,调用上面的Acl if (req.request == "PURGE") { #使用PURGE命令清除缓存 if (!client.ip ~ purge) { #非ACl定义的IP,则不能清除缓存 error 405 "Not allowed."; } return (lookup); } if (req.restarts == 0) { if (req.http.x-forwarded-for) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } } # 不正常的访问不缓存 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); } # 对图片及压缩文件的 Accept-Encoding 统一化 提高命中率 if (req.http.Accept-Encoding) { if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") { # No point in compressing these unset 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 unset req.http.Accept-Encoding; } } ############# 自定义主机规则开始 ############ if (req.url ~ "^http://") { set req.url = regsub(req.url, "http://[^/]*", ""); } if (req.http.host ~ "^img.test.com") { # 删除COOKIE 提高命中 # unset req.http.Cookie; set req.backend = img; } elseif (req.http.host ~ "^www.test.com") { set req.backend = app; } else { error 200 "Unknown virtual host"; } # 扩展名为 php|cgi|asp|jsp|do|aspx 脚本的不缓存 if (req.url ~ "\.(php|cgi|asp|jsp|do|aspx)($|\?)") { return (pass); } ############# 自定义主机规则结束 ############ # 不缓存GET或HEAD以外的请求 if (req.request != "GET" && req.request != "HEAD") { return (pass); } # 不缓存验证信息和Cookie if (req.http.Authorization || req.http.Cookie) { return (pass); } # 所有缓存控制为 no-cache 的不缓存 if (req.http.Cache-Control ~ "no-cache") { return (pass); } return (lookup); } sub vcl_hit { if (req.request == "PURGE") { set obj.ttl = 0s; error 200 "Purged."; } return (deliver); } sub vcl_miss { if (req.request == "PURGE") { error 404 "Not in cache."; } } sub vcl_fetch { # 设定默认缓存时长 set beresp.ttl = 300s; #超时时长为300秒 # 定义缓存时长 if (req.url ~ "\.(css|js|html|htm|xsl|xml)$") { set beresp.ttl = 300s; #超时时长为300秒 } # 图片/视频/音频/文档/压缩文件 缓存时常 if (req.url ~ "\.(png|pdf|ppt|doc|docx|chm|rar|zip|bmp|jpeg|swf|ico|mp3|mp4|rmvb|ogg|mov|avi|wmv|swf|txt|png|gif|jpg)$") { set beresp.http.Pragma = "cache"; set beresp.http.Cache-Control = "max-age=31536000, public"; set beresp.ttl = 365d; } # 如果后端状态为 404 则缓存 600s if(beresp.status == 400 && beresp.status == 403 && beresp.status == 404) { set beresp.ttl = 600s; } # 如果后端服务器出现 500/501/502/503/504 错误时进入神圣模式 saintmode if (beresp.status == 500 || beresp.status == 501 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) { set beresp.saintmode = 20s; return (restart); } # grace时长,减少高并发下的穿透和争抢,设置缓存对象过期后还可以保留的时间 set beresp.grace = 5m; return (deliver); } # 交付页面 sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } #去掉 varnish 中的一些头信息(如果你不想保留的话,建议保留 Age,方便查看) unset resp.http.X-Varnish; unset resp.http.Via; return (deliver); } # 自定义错误页面信息 sub vcl_error { set obj.http.Content-Type = "text/html; charset=utf-8"; synthetic {" <?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>"} + obj.status + " " + obj.response + {"</title> </head> <body> <p style='font-family:Tahoma; font-size:14px;'> <b>Status</b>: "} + obj.status + {"<br> <b>Info</b>: "} + obj.response + {"<br> <b>XID</b>: "} + req.xid + {"<br></p> </body> </html> "}; return (deliver); }
启动服务
Usage: /etc/init.d/varnish {start|stop|status|restart|condrestart|try-restart|reload|force-reload}
service varnish start
中文资料:
更多配置可参考:http://my.oschina.net/jean/blog/189916
更多理论知识:http://my.oschina.net/jean/blog/189910
Varnish缓存策略及缓存时间计算方法说明:http://my.oschina.net/jean/blog/189908
Varnish3.0中文入门教程:http://anykoro.sinaapp.com/2012/01/31/varnish3-0中文入门教程
Varnish调优手记:http://my.oschina.net/u/572653/blog/178201
英文资料:
Varnish官方文档:
https://www.varnish-cache.org/docs/3.0/index.html
PHP的Varnish扩展,主要功能VarnishAdmin VarnishStat VarnishLog
http://www.php.net/manual/zh/book.varnish.php
用 Varnish 扩展 PHP 应用程序
http://www.ibm.com/developerworks/cn/opensource/os-php-varnish/