服务器容错 Misbehaving servers
Varnish的一个关键特色就是它有能力防御 web和应用服务器宕机
优雅模式 Grace mode
当几个客户端请求同一个页面的时候,varnish只发送一个请求到后端服务器,然后让那个其他几个请求挂起等待返回结果,返回结果后,复制请求的结果发送给客户端。在一些产品中,这个可能叫请求合并。varnish这些都是自动完成的。
如果您的服务每秒有数千万的点击率,那么这个队列是庞大的。这就有两个潜在的问题:一个是惊群问题——即突然释放大量线程去复制后端的结果,可能会导致负载急剧上升。第二个问题就是没有用户喜欢等待服务器响应。为了解决这个问题,我们可以让varnish保持对象在缓存中,让它不失效,这样就可以使用缓存中内容返回给客户端,而不用担心等待。
所以为了使用过期的 cache 给用户提供服务,我们需要增加他们的 TTL,保存所有cache 中的内容在 TTL过期以后依然可以保持2分钟:
sub vcl_backend_response {
set beresp.grace = 2m;
}
现在Varnish允许在对象过期后2分钟内提供给客户端。同时varnish也将刷新这个对象。刷新动作是异步发生的,新的对象将替换老对象。
你可以在vcl_hit中添加代码来影响这种逻辑的运行,默认看起来是这样的:
sub vcl_hit {
if (obj.ttl >= 0s) {
// A pure unadultered hit, deliver it
return (deliver);
}
if (obj.ttl + obj.grace > 0s) {
// Object is in grace, deliver it
// Automatically triggers a background fetch
return (deliver);
}
// fetch & deliver once we get the result
return (fetch);
}
grace逻辑在这里很明显。如果你开启了健康检查,你可以检查后端是否出了问题,然后直接宽限对象失效时间即可。用如下的if语句替换掉上面的第二个if语句块:
if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) {
return (deliver);
} else {
return (fetch);
}
综上所述,优雅模式解决了两个问题:
提供旧内容给客户端以避免请求堆积。
如果你允许varnish可以提供过期的内容。