我有一个慢速网络应用程序,我将 Varnish 放在前面。所有页面都是静态的(它们不会因不同的用户而异),但它们需要每 5 分钟更新一次,以便包含最新数据。
我有一个简单的脚本 ( wget --mirror
) 每 15 分钟抓取整个网站。每次抓取大约需要 5 分钟。抓取的要点是更新 Varnish 缓存中的每个页面,这样用户就不必等待页面生成(因为所有页面都是最近生成的,这要归功于蜘蛛)。
时间线看起来像这样:
- 00:00:00:缓存刷新
- 00:00:00: Spider 开始爬行以用新页面更新缓存
- 00:05:00: Spider 完成爬行,所有页面更新至 00:15:00
在 0:00:00 和 0:05:00 之间发出的请求可能会访问尚未更新的页面,并且将被迫等待几秒钟才能得到响应。这是不可接受的。
我想做的是,也许使用一些 VCL 魔法,始终将请求从蜘蛛转发到后端,但仍将响应存储在缓存中。这样,用户将永远不必等待页面生成,因为没有 5 分钟的窗口,其中部分缓存为空(服务器启动时可能除外)。
我怎样才能做到这一点?
req.hash_always_miss
应该做的伎俩。不要在蜘蛛运行开始时进行完全缓存刷新。相反,只需将蜘蛛设置为工作 - 在您的 中
vcl_recv
,将蜘蛛的请求设置为始终错过缓存查找;他们将从后端获取一个新副本。当这种情况发生时,直到新响应进入缓存,客户端将继续无缝地获取旧缓存服务(只要它仍在其 TTL 内)。
Shane 上面的回答比这个好。这是一种更复杂且具有额外问题的替代解决方案。请支持 Shane 的回复,而不是这个。我只是展示另一种解决问题的方法。
我最初的想法是
return (pass);
invcl_recv
然后,在请求被获取之后, invcl_fetch
,以某种方式指示 Varnish 它应该缓存该对象,甚至认为它是早些时候专门传递的。事实证明这是不可能的:
因此,次优的做法是像正常请求一样触发查找,但要确保它始终失败。没有办法影响查找过程,所以它总是会命中(假设它被缓存;如果没有,那么它无论如何都会错过并存储)。但我们可以影响
vcl_hit
:我们不能强制它不使用缓存,但我们可以从缓存中清除该对象并重新启动整个过程。现在它回到开头,在 处
vcl_recv
,它最终会在那里进行另一次查找。由于我们清除了我们已经尝试更新的对象,它会丢失,然后获取数据并更新缓存。有点复杂,但它有效。用户卡在清除和存储响应之间的唯一窗口是处理单个请求的时间。不完美,但相当不错。