十六、Directors
Director(不知道怎么翻译合适,所以就保留了)
你也可以将几个后端分组为一组后端。这些组称为directors。这可以提高性能和灵活度。你可以定义几个后端,并把它们归到一个director中
1
2
3
4
5
6
|
backend server1 {
.host =
"192.168.0.10"
;
}
backend server2{
.host =
"192.168.0.10"
;
}
|
现在创建一个director:
01
02
03
04
05
06
07
08
09
10
|
director example_director round-robin {
{
.backend = server1;
}
# server2
{
.backend = server2;
}
# foo
}
|
该director是一个循环director。这代表该director将根据循环基础分发进入的请求。这也是一个随机director,它以随机风格分发请求。但是,如果你的一个服务器down了怎么办?varnish可以将所有的请求,指向一个健康的服务器吗?当然了。这就是下面要说的健康检查。
十七、Health checks
让我们建立一个director,该director具有两个后端并带健康检查。首先让我们定义后端:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
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:
01
02
03
04
05
06
07
08
09
10
|
director example_director round-robin {
{
.backend = server1;
}
# server2
{
.backend = server2;
}
}
|
使用这个director,就通你使用其他director或后端一样。varnish不会发送流量到那些标记为不健康主机。
如果所有的后端都down掉了,varnish也会提供老的内容。关于如何启用这个功能,可以参看Misbehaving servers。
请注意,varnish将为所有已加载的VCL,持续探测是否活动(active)。varnish将合并相同的probe――所以,注意,如果你做了很多VCL加载,就不要改变probe的配置。卸载VCL,将丢弃probe。
十八、Misbehaving servers
varnish有个重要的特性,它可以保护你免受web-和应用服务器的不良行为。
Grace mode
当几个客户端正访问相同页面时,varnish会发送一个请求到后端,并且让其他请求等待,当从后端取回一个副本时。在某些产品中,这称为请求黑那个,varnish会自动做这个。
如果你每秒需要相应成千上万的点击,等待的请求队列就会很巨大。这里有两个潜在问题,一个是thundering herd problem(这个无法翻译。。。wiki有专门的对应解释),突然增加一千个线程去提供内容,会让负载变得很高。第二个,没有人喜欢等。为了解决这个问题,我们指示varnish去保持缓存的对象超过他们的TTL(就是该过期的,不让它过期),并且去提供旧的内容给正在等待的请求。
所以,为了提供旧的内容,首先我们必须有内容去提供。所以,我们使用以下VCL,以使varnish保持所有对象超出了他们的TTL30分钟。
1
2
3
|
sub vcl_fetch {
set
beresp.grace = 30m;
}
|
这样,varnish还不会提供旧对象。为了启用varnish去提供旧对象,我们必须在请求上开启它。下面表示,我们接收15s的旧对象:
1
2
3
|
sub vcl_recv {
set
req.grace = 15s;
}
|
你可能想知道,为什么,如果我们无法提供这些对象,我们在缓存中保持这些对象30分钟?如果你开启健康检查,你可以检查后端是否出问题。如果出问题了,我们可以提供长点时间的旧内容。
1
2
3
4
5
|
if
(! req.backend.healthy) {
set
req.grace = 5m;
}
else
{
set
req.grace = 15s;
}
|
所以,总结下,优雅模式解决了两个问题:
1、 通过提供旧的内容,避免请求扎堆。
2、 如果后端坏了,提供旧的内容。
Saint mode
有时候,服务器会比较奇怪。他们开始抛出随机错误。你可以指示varnish去处 理这些错误,用一种更加优雅得方式――神圣模式。神圣模式可以让你抛弃一个后端服务器的某个页面,并尝试从其他服务器获取,或提供缓存中的旧内容。让我们看看如何在VCL中开启:
1
2
3
4
5
6
7
|
sub vcl_fetch {
if
(beresp.status == 500) {
set
beresp.saintmode = 10s;
restart;
}
set
beresp.grace = 5m;
}
|
当我们设置beresp.saintmode为10秒时,varnish会不请求该服务器10秒。或多或少可以算是一个黑名单。restart被执行时,如果我们有其他后端可以提供该内容,varnish会请求它们。当没有其他后端可用,varnish就会提供缓存中的旧内容。
这真的是可以救命的。
清楚grace-和saint 模式的限制
当请求正在被获取时,如果你的请求失败,会被扔到vcl_error中。由于vcl_error对数据集的访问有很大显示,所以你不能启用优雅模式和神圣模式。在以后发布的版本中会解决这个问题,但是这里我们还是可以做些什么的。
1、 声明总是出状况的后端
2、 在vcl_error中设置magic marker
3、 重启事务
4、 注意vcl_recv中的magic marker,并设置后端为之前提到的。
5、 varnish现在将提供旧任何可获得的数据
God mode
还没有实现。:-)
十九、Advanced topics
该教程涉及了varnish中的基础。如果你通读了它,你现在应该已经有运行varnish的能力了。这里是一个简短的我们在本教程中没有谈到的专题概览。
更多VCL
VCL比至少我们所说的要复杂一点。这里有一些更多我们没有谈到的子程序和action可用。要查看VCL的完整教程,可以参看VCL的手册页面――reference-vcl
使用内嵌C扩展varnish
你可以使用内嵌C去扩展varnish。注意,这种方式可能会把varnish搞乱。因为C语言在varnish缓存处理中运行,所以如果你的代码出现一点错误,varnish就会崩溃。
我看到的第一个内嵌C应用是写入syslog:
01
02
03
04
05
06
07
08
09
10
|
# 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看上去是这样的:
1
2
3
4
5
6
|
<
HTML
>
<
BODY
>
The time is: <
esi:include
src
=
"/cgi-bin/date.cgi"
/>
at this very moment.
</
BODY
>
</
HTML
>
|
通过在vcl_fetch中,设置do_esi为true,来让ESI工作:
1
2
3
4
5
|
sub vcl_fetch {
if
(req.url ==
"/test.html"
) {
set
beresp.do_esi =
true
; /* Do ESI processing */
}
}
|
二十、Troubleshooting Varnish
有时候varnish会发神经。为了帮助你理解发生了,这里有一些你可以检查的地方。varnishlog,/var/log/syslog, /var/log/messages都是varnish会留下相关线索的地方。
当varnish没有启动
有时varnish会不启动。在你的机器上,为何varnish不启动,这里有个经常引起的原因。从/dev/null的权限错误,到其他进程阻塞了端口。
以debug模式启动varnish,查看发生了什么。
通过以下代码启动varnish:
1
|
# varnishd -f /usr/local/etc/varnish/default.vcl -s malloc,1G -T 127.0.0.1:2000 -a 0.0.0.0:8080 -d
|
注意,-d选项(开启debug模式)。这将给你一些关于发生什么的信息。让我们看看varnish将如何响应那些监听此端口上的东西:
1
|
# varnishd -n foo -f /usr/local/etc/varnish/default.vcl -s malloc,1G -T 127.0.0.1:2000 -a 0.0.0.0:8080 -d
|
01
02
03
04
05
06
07
08
09
10
|
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”,指示主进程开始缓存。
1
2
3
4
|
start
bind(): Address already in use
300 22
Could not open sockets
|
这里我们发现个问题。有些其他什么绑定在了varnish的HTTP端口上了。如果这没有什么帮助,就在IRC上尝试下trace、truss或come find us。
Varnish崩溃
当varnish损坏,子进程就会崩溃。常常母进程将通过再次重启子进程去解决。任何错误都会被记录在syslog中。看上去会像以下:
1
2
3
4
5
|
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
|
尤其是,如果你在Linux上看到“Error in munmap”错误,你可能需要增加可获得的映射数量。Linux被限制最大64k映射(映射表示将文件或其他对象映射到内存)。设置sysctl.conf中的vm.max_max_count,将使你提高此限制。你可以通过统计/proc/$PID/maps的数量,来检查你程序使用的映射数量。
记录在这里的,是一个很奇怪的问题。但是充满希望的Google将提供答案,如果你曾经遇到此问题的话。
Varnish提示Guru meditation(一种错误提示方式,见wiki)
首先在varnishlog中,找到相关日志条目,这可能会提供一些线索。因为varnishlog记录了很多数据,所以可能很难查到我们需要的条目。你可以通过执行一下的命令,设置varnishlog记录所有的503错误:
1
|
$ varnishlog -c -m TxStatus:503
|
如果错误只是发生在一会儿前,事务可能还存在于共享内存日志碎片中。要让varnishlog去处理所有共享内存日志只要添加-d选项:
1
|
$ varnishlog -d -c -m TxStatus:503
|
要进一步了解不同参数的解释和过滤能力,请看varnishlog手册页面。
Varnish不缓存
请查看Achieving a high hitrate