当后端生病的时候,Varnish可以忽略打通

如果所有的后端都被标记为“恶心”,有没有办法让Varnish 4忽略高速caching中的任何传递对象?

以下是我试图改进的故障场景:

  • 起初后端都是健康的,performance很好,返回有效内容为200.Varnish正在caching这些页面,并根据它们的TTL服务它们。
  • 有些事情会中断,比方说数据库查询开始的时间要比平时长。 后端开始缓慢地返回页面。 然后最终请求开始超时,后端开始返回“内部服务器错误”(状态500)。
  • Varnish根据默认的vcl_backend_response查看这些响应,并将它们标记为TTL为120s的vcl_backend_response
  • 最后,健康检查启动,清最终标志着所有的后端病态。
  • 现在随着更多的请求进来,Varnish在caching中看到一个传递对象,并决定需要做一个后端提取。 除了所有的后端生病,所以导致503“后端抓取失败”。
    这503个响应会持续2分钟,这取决于第一个不可caching的响应(标记为传输命中)的时间以及后端全部显着恶化的时间。
  • 在命中对象从高速caching(120s)过期后,Varnish开始将这些请求作为常规命中来处理,并以宽限模式提供高速caching的200状态页面(根据默认的vcl_hit – “ if (obj.ttl + obj.grace > 0) ....

我提出的一个解决方法是,如果来自状态500的响应,则缩短传递命中对象的TTL:

 sub vcl_backend_response { if (beresp.ttl <= 0s && beresp.status == 500) { set beresp.ttl = 10s; set beresp.uncacheable = true; # return inside this if statement to allow builtin vcl_backend_response to run return (deliver); } } 

其他可能性是调整健康检查的间隔和阈值,或者提出更好的健康检查。

但是除此之外,有没有办法明确告诉Varnish:“是的,你有一个通行证,但看起来 – 所有的后端生病了!不要打扰,现在转换到宽限期模式。

如果你想要这样的行为, 当你从后端得到500个响应的时候你应该避免创buildhit-for-pass对象

假设(1)您总是请求相同的可cachingURL /对象X; (2)对象X当前存储在清漆存储器中,TTL为1小时,宽度为24小时。 现在假设以下时间表:

  • t = 0:某些客户请求X去清漆。 该对象已被caching和新鲜,所以Varnish将其返回给客户端。 没有后端请求。
  • t = 1:后端被破坏,从现在开始,所有的请求都回复500。
  • t = 3601:有些客户要求X去清漆。 该对象被caching但是被停止,因此Varnish将其返回给客户端并触发后台后端请求来更新caching的对象X.
  • t = 3602:后台后台请求获得500响应。 命中通行对象以120s的TTL存储。 该对象覆盖停止的对象X.
  • t = 3603:有些客户要求X去清漆。 find一个通行对象并执行一个后端请求。 500响应被发送到客户端。
  • t = 4000:有些客户要求X去清漆。 对象X不再处于caching中,而后端在前一段时间被标记为病态。 一个503响应将被发送到客户端:清漆不能接触后端(它被标记为生病)并且清漆不能返回宽限内容(它在t = 3602时被通过命中对象覆盖)。

当你从后端得到500个响应时,这里的解决scheme将避免创build点击对象。 而是简单地放弃请求。 在t = 3603和t = 4000这样的方式,你会发送一个停滞的对象副本到客户端。