第一部分:部署篇
作为一个Server Service,部署是最基本的,同时也没有太多需要说明的。按照官方的教程,一运行便可了。但是需要注意的是,–perfix什么的,具体怎么设置的,可要好好的记住,否则,以后要查起来,可就没有头绪了。另外,装了什么样的插件也要清楚的。
下面介绍下,安装方法。
针对CentOS系统,有两种方法安装,一种是通过rpm,另一种是通过源码安装。
一、通过rpm安装:
使用varnish-cache.org库,运行
rpm --nosignature -i http://repo.varnish-cache.org/redhat/varnish-3.0/el5/noarch/varnish-release-3.0-1.noarch.rpm
然后运行,
yum install varnish
–no-signature只在初始安装时需要,因为Varnish的GPG key还不再yum的keyring中。
二、通过源码编译安装:
1、获得源码文件
从http://repo.varnish-cache.org/source上下载tar包,找release版的。
或者你可以通过git克隆一个。Git clone git://git.varnish-cache.org/varnish-cache
要注意通过git签出的版本会比一般情况需要更多依赖包,尤其是Python Docutils和Sphinx。
2、所需要的依赖包
automake autoconf libtool ncurses-devel libxslt groff pcre-devel pkgconfig
3、配置和编译
确保上面的依赖包都满足,这样才能配置。基本命令如下
cd varnish-cache sh autogen.sh sh configure make
第二部分:应用篇
当我们部署好之后,自然就是要学习怎么使用,Linux下,尤其是Server的Linux怎么可能有GUI呢。所以,学习配置文件的语法和控制台就很关键了。
下面是要的学习内容目录,我们还是依次进行。
Backend servers Starting Varnish Logging in Varnish Sizing your cache Put Varnish on port 80 Varnish Configuration Language – VCL Statistics Achieving a high hitrate Cookies Vary Pitfall – Vary: User-Agent Purging and banning Edge Side Includes Running inside a virtual machine (VM) Advanced Backend configuration Directors Health checks Misbehaving servers Advanced topics Troubleshooting Varnish
一、Backend servers
Varnish有后端(或称为源)服务器的概念。后端服务器是指Varnish提供加速服务的那台,通常提供内容。
第一件要做的事情是告诉Varnish,哪里能找到要加速的内容。打开varnish配置文件,源码包安装的在/usr/local/etc/varnish/default.vcl中,rpm安装的在/etc/varnish/default.vcl中。
顶部有如下注释:
# backend default { # .host = "127.0.0.1"; # .port = "8080"; # }
backend default { .host = "127.0.0.1"; .port = "80"; }
三、Logging in Varnish
在Varnish中,日志的工作方式,是一个很好特性。Varnish将日志记录到共享内存片段,而不是记录到一个普通文件中。当记录到内存片段的最后处,会再从头开始记,覆写老数据。这个比记录到文件要快的多,而且不需要磁盘空间。
另一方面,如果你没有执行程序去将这些日志写到磁盘中的话,他们是会消失的。
Varnishlog是一个用来查看Varnish日志的程序。Varnishlog提供给我们原始日志。这里还有其他客户端,之后我们会介绍。
在启动varnish的终端窗口,我们输入varnishlog,然后按回车。
你会看到如下内容,使用”.”可以缓缓滚动:
0 CLI - Rd ping 0 CLI - Wr 200 PONG 1273698726 1.0
这是varnish主进程,检查缓存进程,看是否一切正常。
现在在浏览器,重新加载页面,显示你的web应用。你会看到如下内容:
11 SessionOpen c 127.0.0.1 58912 0.0.0.0:8080 11 ReqStart c 127.0.0.1 58912 595005213 11 RxRequest c GET 11 RxURL c / 11 RxProtocol c HTTP/1.1 11 RxHeader c Host: localhost:8080 11 RxHeader c Connection: keep-alive
vcl_fetch
vcl_fetch是在文档从后端被成功接收后调用的。通常用于调整响应头信息,触发ESI处理,万一请求失败就换个后端服务器。
在vcl_fecth中,你还可以使用请求对象req。还有个后端响应对象beresp。Beresp包含了后端的HTTP头信息。
actions
最常用的action如下:
pass:当返回pass的时候,请求和随后的响应都将被传到后端服务器,或从那里传回。不会被缓存。pass可以在vcl_recv中被返回。
hit_for_pass:类似与pass,但是只有vcl_fetch可以用。不像pass,hit_for_pass将在缓存中创建一个hitforpass对象。这有个副作用,就是缓存了不像缓存的东西。同时会将未缓存的请求传到后端。在vcl_recv中这样的逻辑不是必须的,因为它发生在任何潜在对象队列发生之前。
lookup:当在vcl_recv中返回lookup时,就等于你告诉varnish发送缓存中的内容,即使该请求应该是被pass的。在vcl_fetch中不能使用lookup。
pipe:pipe也可以在vcl_recv中返回。pipe缩短了客户和后端的环路链接,并且varnish将只是待在哪里,来回偏移字节。varnish不会在意来回发送的数据,所以你的日志是不完整的。注意一个客户会基于相同链接发送几个请求,当使用HTTP 1.1时。所以在实际返回pipe之前,你需要让varnish添加”Connection:close”的头信息。
deliver:投递缓存对象给客户。经常在vcl_fetch中使用。
请求,响应和对象
在VCL中,有三种重要的数据结构。请求:来自客户端;响应:来自后端服务器;对象:存储在缓存中。
在VCL中你应该知道以下结构。
req:请求对象。当varnish接受了请求,req就会创建并生产。许多在vcl_recv中要做的工作都需要用到req。
beresp:后端响应对象。包含了从后端返回的对象的头信息。vcl_fetch中,你会使用beresp对象。
obj:缓存了的对象。大多数是驻留在内存中的只读对象。obj.ttl是可以写的,剩下的都是只读的。
操作符
VCL中可用的操作符如下,稍后可以看例子:
=:赋值
==:比较
~:匹配。可使用正则表达式或ACLs
!:取反
&&:逻辑与
||:逻辑或
例1 – 操作头信息
移除所有在web服务器的/images目录中的对象的cookie:
sub vcl_recv { if (req.url ~ "^/images") { unset req.http.cookie; } }
现在,当请求传到后端服务器时,他是不带有cookie头信息的。需要在意的是if语句,它根据正则表达式匹配了URL(属于请求对象)。注意匹配操作符。如果它匹配,请求的cookie头信息就会被删除。
例2 – 操作beresp
这里如果匹配某种条件,我们就重写beresp的TTL属性
sub vcl_fetch { if (req.url ~ "\.(png|gif|jpg)$") { unset beresp.http.set-cookie; set beresp.ttl = 1h; } }
例3 – ACLs
你创建了一个使用acl关键字的访问控制列表。你可以使用匹配操作符去判断客户端的IP地址是否与一个ACL匹配。
# Who is allowed to purge.... 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."; } }
八、Achieving a high hitrate
现在Varnish已经运行,并且你可以通过Varnish访问你的站点。除非你的应用是专门为在一个web加速器后工作而写的,否则为了在Varnish中获得高命中率,你可能需要在配置或应用上做一些修改。
除非varnish完全确定缓存你的数据室安全,否则varnish是不会缓存的。所以,为了让你明白varnish是如何确定的,并使如何缓存页面的,我将通过一些很有用工具去引导你:
注意你需要一个工具去观察传输于你和web服务器之间的HTTP头信息。在varnish服务器上,首先是使用varnishlog和varnishtop,但有时候需要客户端工具去搞清楚。下面就是我们用到的。
工具:varnishtop
你可以使用varnishtop确定出后端命中最多的URL。varnishtop –i txurl是必须的命令。你可以在前一节Statistics中,看到一些其他的varnishtop的例子。
工具:varnishlog
当你已经确定了最常发送给后端的URL是多少时,你可以使用varnishlog去查看完整的请求。varnishlog –c –o /foo/bar将给你来自客户端(-c)的完整(-o)的匹配/foo/bar的请求。
对于扩展诊断头信息,可以参看:http://www.varnish-cache.org/trac/wiki/VCLExampleHitMissHeader
工具:lwp-request
lwp-request是perl的World-Wide Web library中的一部分。它是一些基本的程序,这些程序可以处理HTTP请求,并且给你结果。我通常使用两个程序,GET和HEAD。
vg.no是第一个使用varnish的站点,站点的创建者很明白varnish。所以,让我们看看他们的HTTP头信息。我们对他们的首页发一个GET请求:
$ GET -H 'Host: www.vg.no' -Used http://vg.no/ GET http://vg.no/ Host: www.vg.no User-Agent: lwp-request/5.834 libwww-perl/5.834 200 OK Cache-Control: must-revalidate Refresh: 600 Title: VG Nett - Forsiden - VG Nett X-Age: 463 X-Cache: HIT X-Rick-Would-Never: Let you down X-VG-Jobb: http://www.finn.no/finn/job/fulltime/result?keyword=vg+multimedia Merk:HeaderNinja X-VG-Korken: http://www.youtube.com/watch?v=Fcj8CnD5188 X-VG-WebCache: joanie X-VG-WebServer: leon
OK。我们来解释一下。GET通常发送HTTP0.9请求,其缺少Host头信息。所以我通过-H添加了一个Host头信息。-U打印请求头信息,-s打印响应状态,-e打印响应头信息,-d丢弃实际内容。我们并不关心内容,只要头信息。
你可以发现,VG在他们的头信息中添加了一些信息。像X-Rick-Would-Never表示了vg.no的某种奇怪的幽默。其他,像X-VG-Webcache是用来调试的。
所以,你可以检查一个站点的特定URL是否设置了cookie,只需要:
GET -Used http://example.com/ |grep ^Set-Cookie
工具:实时HTTP头信息
Firefox也有个插件。Live HTTP Headers可以显示你发送和接受到的头信息。你可以通过google找到“Live HTTP Header”,或者到https://addons.mozilla.org/en-US/firefox/addon/3829/可以找到。
HTTP头信息的角色
随着每个HTTP请求和响应变成一群携带原数据的头信息。varnish将查看这些头信息,以确定这里的内容是否适合缓存,以及缓存多久。
请注意,当考虑这些头信息时候,实际上varnish只考虑真实web服务器中varnish自己的那部分。考虑的理论依据都在于你的控制。
术语surrogate origin cache没有在IETF so RFC2616中很好的定义。所以varnish不同的工作方式可能会和你的预期不同。
让我们看看你应该知道的重要的头信息:
Cache-Control
Cache-Control指定了缓存如何处理内容。varnish关心max-age参数,并用它来计算对象的TTL。
“Cache-Control:nocache”是被忽略的,如果你需要,你也可以方便的增加支持。
所以,确保你发出的Cache-Control头信息具有max-age。你可以看看Varnish软件的联盟服务器发出了什么:
$ GET -Used http://www.varnish-software.com/|grep ^Cache-Control Cache-Control: public, max-age=600 Age
varnish添加了一个Age头信息,以指示在Varnish中该对象被保持了多久。你可以通过varnishlog像下面那样抓出Age:
varnishlog -i TxHeader -I ^Age
Pragma
一个HTTP 1.0服务器可能会发送”Pragma:nocache”。Varnish忽略这种头信息。在VCL中你可以很方便的增加对这种头信息的支持。
在vcl_fetch中:
if (beresp.http.Pragma ~ "nocache") { pass; } Authorization
如果varnish看到授权头信息时,它会pass该请求。如果这不是你希望的,你可以unset这个头信息。
Overriding the time-to-live(ttl)
有时你的后端会误操作。根据你的安装,在varnish中覆写ttl会比修复你某些麻烦的后端要简单的多。
你需要VCL去确定你想要的对象,然后你将beresp.ttl的值设置成你想设置的值。
sub vcl_fetch { if (req.url ~ "^/legacy_broken_cms/") { set beresp.ttl = 5d; } }
该例会为你网站上过去的遗留物,将TTL设置为5天。
Forcing caching for certain requests and certain responses
由于你还在使用那些麻烦的不能很好工作的后端,你可能会想再varnish中覆写更多的内容。我们推荐你尽可能多的使用默认缓存规则。尽管强制varnish在缓存中查找一个对象很简单,但我们还是不推荐。
Normalizing your namespace
一些站点可以通过很多主机名访问。比如, http://www.varnish-software.com/ , http://varnish-software.com/和http://varnishsoftware.com/。这些都指向同一个站点。由于varnish不知道他们的区别,varnish会为每个主机名的每个页面做缓存。你可以通过在你的web服务器配置中设置跳转或者使用VCL来缓解这个情况:
if (req.http.host ~ "(?i)^(www.)?varnish-?software.com") { set req.http.host = "varnish-software.com"; }
Ways of increasing your hitrate even more
接下来的章节,会阐述进一步提高命中率的方法,尤其在cookies的章节中。
Cookies
Vary
Purging and banning
Edge Side Includes
九、Cookies
varnish不会缓存来自后端的具有Set-Cookie头信息的对象。同样,如果客户端发送了一个Cookie头信息,varnish将绕过缓存,直接发给后端。
这可能太过保守。很多站点使用Google Analytics(GA)去分析他们的流量。GA通过设置cookie去跟踪。这个cookie是供客户端的JavaScript程序使用的,服务器是不需要的。
对很多web应用,它会完全忽视cookies,除非你正在访问网站的特定部分。在vcl_recv中的下面的VCL代码块将忽略cookies,除非你访问/admin/:
if ( !( req.url ~ ^/admin/) ) { unset req.http.Cookie; }
非常简单。然后,如果你需要做更复杂的处理,像在几个cookie中移除其中一个,事情就麻烦了。遗憾的是,varnish没有很好的工具去操作cookie。我们不得不使用正则表达式去做这件事情。如果你熟悉正则表达式,你就明白怎么办了。如果你不熟悉,我建议你找本书好好学习下,或者通过pcrepattern手册页面或其他的在线教程。
让我展示给你看看,varnish软件是用什么的。我们使用一些GA的跟踪cookie或其他类似工具的cookie。这些cookie都是供JavaScript使用的。varnish和其联盟站不需要这些cookie,并且因为varnish会因为这些cookie不缓存页面,所以当客户端发送cookie时,我们将在VCL中丢弃这些非必要的cookie。
下面的VCL中,我们丢弃了所有的以“_”开头的cookie:
// Remove has_js and Google Analytics __* cookies. set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", ""); // Remove a ";" prefix, if present. set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
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 { # unkown algorithm remove req.http.Accept-Encoding; } }
十二、Purging and banning
最有效提升命中率的方法是增加你对象的ttl(time-to-live存活时间)。但是,你要知道,在微博时代,提供过时的内容是很不利于业务的。
解决方案是,当有新内容时,就通知varnish。这可以通过两个机制实现。HTTP清理(PURGE,以下称PURGE)和禁止(BAN,以下简称BAN)。首先让我们解释下HTTP PURGE
HTTP PURGE
PURGE(清理)是指当你选出一个缓存对象时,根据其变化的内容进行丢弃。通常PURGE是通过HTTP的PURGE方法进行调用的(即method=purge,这个purge是http协议中没有预定义的,应该是varnish中扩展的)。
HTTP PURGE类似于HTTP GET请求,只是method是PURGE。事实上,你可以调用任何你希望的method,不过许多人都倾向于使用PURGE。Squid支持相同的机制。为了在varnish支持PURGE,你需要以下代码:
acl purge { "localhost"; "192.168.55.0/24"; } sub vcl_recv { # allow PURGE from localhost and 192.168.55... if (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } return (lookup); } } sub vcl_hit { if (req.request == "PURGE") { purge; error 200 "Purged."; } } sub vcl_miss { if (req.request == "PURGE") { purge; error 200 "Purged."; } }
正如你看到的。我们使用了新的VCL子程序,vcl_hit和vcl_miss。当我们调用lookup时,varnish将尝试在缓存中查找对象。要么命中,要么丢失,然后调用相应的子程序。在vcl_hit中,我们可以获得存于缓存中的对象,并且可以设置它的TTL。
所以,对于example.com,要让它的首页失效(表示要拿新的内容),可以这样请求varnish:
PURGE / HTTP/1.0 Host: example.com
之后,Varnish就会丢弃主页。这会移除所有变量,如vary所定义的。
Ban
这是另一个让内容失效的方法。禁止(BAN),你可以将其认为是一种过滤器。你禁止你的缓存提供某些内容。你可以根据我们有的元数据,进行禁止。
Varnish支持禁止功能,并且可以再CLI接口中获得。对于VG,如果想禁止属于example.com的png对象,他们可以分发以下内容:
ban req.http.host == "example.com" && req.http.url ~ "\.png$"
真的很强大。
当在缓存中命中对象时且在投递之前,就会检查其是否BAN。一个对象只会被较新的BAN检查。
只对beresp.*起作用的BAN,由背景工作线程运行着,称为ban lurker。ban lurker将检查堆,看看是否匹配对象,并且去除匹配对象。ban lurker的频度(活跃度),可以通过ban_lurker_sleep参数控制。
禁止那些较老的,对于缓存中最老的对象不经验证就直接丢弃。如果你有很多具有长TTL对象,这些对象很少被访问,那么你会累积大量的禁止。这会影响CPU的利用率和性能。
你可以通过HTTP向varnish添加BAN。这样做需要一些VCL:
sub vcl_recv { if (req.request == "BAN") { # Same ACL check as above: if (!client.ip ~ purge) { error 405 "Not allowed."; } ban("req.http.host == " + req.http.host + "&& req.url == " + req.url); # Throw a synthetic page so the # request won't go to the backend. error 200 "Ban added"; } }
十三、Edge Side Includes
Edge Side Includes(边界情况包含)是一种语言,用来包含在其他web页面中的web页面片断。可以认为他是一个通过HTTP实现的HTML包含语句。
在许多web站点,许多内容是各页面间共享的。为每个页面重新生成这些内容是很浪费的,并且ESI(Edge Side Includes的缩写)致力于让你为每个片断单独决定缓存策略。
在varnish中,我们只实现了ESI的一个小的子集。自2.1起,我们就有三个ESI语句:
esi:include
esi:remove
<!–esi …–>
基于变量和cookie的内容替换还没有实现,但是已经在计划中了。
例子:esi include
让我们看看如何使用它。这段简单的cgi脚本,输出了日期:
#!/bin/sh echo 'Content-type: text/html' echo '' date "+%Y-%m-%d %H:%M"
<HTML> <BODY> The time is: <esi:include src="/cgi-bin/date.cgi"/> at this very moment. </BODY> </HTML>
sub vcl_fetch { if (req.url == "/test.html") { set beresp.do_esi = true; /* Do ESI processing */ set beresp.ttl = 24 h; /* Sets the TTL on the HTML above */ } elseif (req.url == "/cgi-bin/date.cgi") { set beresp.ttl = 1m; /* Sets a one minute TTL on */ /* the included object */ } }
<esi:include src="http://www.example.com/ad.html"/> <esi:remove> <a href="http://www.example.com">www.example.com</a> </esi:remove>
例子:<!—esi…–>
这是一个特殊的构造,允许ESI标记的HTML呈现,而无需处理。当处理页面时,ESI处理器将移除开始(<–esi)和结尾(–>),然而仍然会处理其内容。如果页面没有被处理,它将会留下,编程HTML/XML的注释标签。例如:
<!--esi <p>Warning: ESI Disabled!</p> </p> -->
十五、Advanced Backend Configuration
某些情况,你可能需要让varnish缓存几个服务器的内容。你可能希望varnish映射所有URL到一个或多个主机。这里有许多选项。
比如,我们需要引入一个Java应用到PHP网站。我们的Java应用会处理以/java/开头的URL。
我们将东西起起来,运行在8000端口。现在来看看default.vcl:
backend default { .host = "127.0.0.1"; .port = "8080"; }
我们添加新的后端:
backend java { .host = "127.0.0.1"; .port = "8000"; }
现在我们要指示,发送不同URL的规则。看看vcl_recv:
sub vcl_recv { if (req.url ~ "^/java/") { set req.backend = java; } else { set req.backend = default. } }
非常简单。现在先让我们停一下,考虑一下这里的情况。如你所见,你可以根据任意情况定义如何选择后端。如果你发送移动设备的请求到不同的后端,可以做类似的操作,if(req.User-agent ~ /mobile/)
十六、Directors
Director(不知道怎么翻译合适,所以就保留了)
你也可以将几个后端分组为一组后端。这些组称为directors。这可以提高性能和灵活度。你可以定义几个后端,并把它们归到一个director中
backend server1 { .host = "192.168.0.10"; } backend server2{ .host = "192.168.0.10"; }
现在创建一个director:
director example_director round-robin { { .backend = server1; } # server2 { .backend = server2; } # foo }
十七、Health checks
让我们建立一个director,该director具有两个后端并带健康检查。首先让我们定义后端:
backend server1 { .host = "server1.example.com"; .probe = { .url = "/"; .interval = 5s; .timeout = 1 s; .window = 5; .threshold = 3; } } backend server2 { .host = "server2.example.com"; .probe = { .url = "/"; .interval = 5s; .timeout = 1 s; .window = 5; .threshold = 3; } }
probe是新的内容。varnish将使用probe对每个后端进行健康检查。其选项有:
url:定义什么样的URL需要varnish(感觉这里应该是做处理的意思)请求。
interval:查询的间隔时长
timeout:probe的超时时间
window:varnish将保持一个结果的滑动窗(该滑动窗不是实际的窗体,是一种流量控制方法,允许发送方在停止并等待确认前可以连续发送多个分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输。)。这里窗口有5个确认点。
threshold:上次查询的.window数量为多少时,就代表后端是健康的。
initial:当varnish启动时候,用多少个probe去探测健康情况——默认情况,此数量与threshold的数量一致。
现在我们定义director:
director example_director round-robin { { .backend = server1; } # server2 { .backend = server2; } }
十八、Misbehaving servers
varnish有个重要的特性,它可以保护你免受web-和应用服务器的不良行为。
Grace mode
当几个客户端正访问相同页面时,varnish会发送一个请求到后端,并且让其他请求等待,当从后端取回一个副本时。在某些产品中,这称为请求黑那个,varnish会自动做这个。
如果你每秒需要相应成千上万的点击,等待的请求队列就会很巨大。这里有两个潜在问题,一个是thundering herd problem(这个无法翻译。。。wiki有专门的对应解释),突然增加一千个线程去提供内容,会让负载变得很高。第二个,没有人喜欢等。为了解决这个问题,我们指示varnish去保持缓存的对象超过他们的TTL(就是该过期的,不让它过期),并且去提供旧的内容给正在等待的请求。
所以,为了提供旧的内容,首先我们必须有内容去提供。所以,我们使用以下VCL,以使varnish保持所有对象超出了他们的TTL30分钟。
sub vcl_fetch { set beresp.grace = 30m; }
这样,varnish还不会提供旧对象。为了启用varnish去提供旧对象,我们必须在请求上开启它。下面表示,我们接收15s的旧对象:
sub vcl_recv { set req.grace = 15s; }
你可能想知道,为什么,如果我们无法提供这些对象,我们在缓存中保持这些对象30分钟?如果你开启健康检查,你可以检查后端是否出问题。如果出问题了,我们可以提供长点时间的旧内容。
if (! req.backend.healthy) { set req.grace = 5m; } else { set req.grace = 15s; }
所以,总结下,优雅模式解决了两个问题:
1、 通过提供旧的内容,避免请求扎堆。
2、 如果后端坏了,提供旧的内容。
Saint mode
有时候,服务器会比较奇怪。他们开始抛出随机错误。你可以指示varnish去处 理这些错误,用一种更加优雅得方式——神圣模式。神圣模式可以让你抛弃一个后端服务器的某个页面,并尝试从其他服务器获取,或提供缓存中的旧内容。让我们看看如何在VCL中开启:
sub vcl_fetch { if (beresp.status == 500) { set beresp.saintmode = 10s; restart; } set beresp.grace = 5m; }
十九、Advanced topics
该教程涉及了varnish中的基础。如果你通读了它,你现在应该已经有运行varnish的能力了。这里是一个简短的我们在本教程中没有谈到的专题概览。
更多VCL
VCL比至少我们所说的要复杂一点。这里有一些更多我们没有谈到的子程序和action可用。要查看VCL的完整教程,可以参看VCL的手册页面——reference-vcl
使用内嵌C扩展varnish
你可以使用内嵌C去扩展varnish。注意,这种方式可能会把varnish搞乱。因为C语言在varnish缓存处理中运行,所以如果你的代码出现一点错误,varnish就会崩溃。
我看到的第一个内嵌C应用是写入syslog:
# The include statements must be outside the subroutines. C{ #include <syslog.h> }C sub vcl_something { C{ syslog(LOG_INFO, "Something happened at VCL line XX."); }C } Edge Side Includes
varnish可以通过把不同页面放到一起,缓存、创建web页面。这些片断可以有自己的缓存策略。如果你的网站有一个显示最热的5篇文章的列表,该列表可能被作为片断缓存起来,并且被包含在其他页面中。使用属性可以很好地提升命中率并降低服务器负载。ESI看上去是这样的:
<HTML> <BODY> The time is: <esi:include src="/cgi-bin/date.cgi"/> at this very moment. </BODY> </HTML>
sub vcl_fetch { if (req.url == "/test.html") { set beresp.do_esi = true; /* Do ESI processing */ } }
storage_malloc: max size 1024 MB. Using old SHMFILE Platform: Linux,2.6.32-21-generic,i686,-smalloc,-hcritbit 200 193 ----------------------------- Varnish Cache CLI. ----------------------------- Type 'help' for command list. Type 'quit' to close CLI session. Type 'start' to launch worker process.
现在varnish已经启动。只有主进程运行着,在调试模式下,缓存是不会运行的。现在你正处于控制台。你可以通过分发“start”,指示主进程开始缓存。
start bind(): Address already in use 300 22 Could not open sockets
这里我们发现个问题。有些其他什么绑定在了varnish的HTTP端口上了。如果这没有什么帮助,就在IRC上尝试下trace、truss或come find us。
Varnish崩溃
当varnish损坏,子进程就会崩溃。常常母进程将通过再次重启子进程去解决。任何错误都会被记录在syslog中。看上去会像以下:
Mar 8 13:23:38 smoke varnishd[15670]: Child (15671) not responding to CLI, killing it. Mar 8 13:23:43 smoke varnishd[15670]: last message repeated 2 times Mar 8 13:23:43 smoke varnishd[15670]: Child (15671) died signal=3 Mar 8 13:23:43 smoke varnishd[15670]: Child cleanup complete Mar 8 13:23:43 smoke varnishd[15670]: child (15697) Started