我正在缓存动态生成的页面(
PHP-FPM,NGINX)并且在它们前面有清漆,这非常有效.
但是,一旦达到缓存超时,我会看到:
>新客户请求页面
> varnish识别缓存超时
>客户等待
> varnish从后端获取新页面
> varnish将新页面传递给客户端(并且还有页面缓存,用于下一个立即获取它的请求)
我想做的是:
>客户请求页面
> varnish识别超时
> varnish将旧页面传递给客户端
> varnish从后端获取新页面并将其放入缓存中
在我的情况下,它不是过时信息是一个大问题的网站,尤其是当我们从几分钟谈论缓存超时时.
但是,我不希望惩罚用户排队,而是立即提供一些东西.这有可能吗?
为了说明,这是一个针对我的服务器运行围攻5分钟的示例输出,该服务器被配置为缓存一分钟:
HTTP/1.1,200, 1.97, 12710,/,1,2013-06-24 00:21:06
...
HTTP/1.1,200, 1.88, 12710,/,1,2013-06-24 00:21:20
...
HTTP/1.1,200, 1.93, 12710,/,1,2013-06-24 00:22:08
...
HTTP/1.1,200, 1.89, 12710,/,1,2013-06-24 00:22:22
...
HTTP/1.1,200, 1.94, 12710,/,1,2013-06-24 00:23:10
...
HTTP/1.1,200, 1.91, 12709,/,1,2013-06-24 00:23:23
...
HTTP/1.1,200, 1.93, 12710,/,1,2013-06-24 00:24:12
...
我遗漏了在0.02左右运行的数百个请求.但它仍然让我感到担心的是,用户必须等待将近2秒的原始HTML.
我们不能在这里做得更好吗?
(我遇到了Varnish send while cache,听起来很相似,但不完全是我想要做的.)
解
Shane Madden的答案包含了解决方案,但我没有马上意识到这一点.我没有在我的问题中包含另一个细节因为我认为它不相关,但实际上它是.
我目前使用的CMS解决方案有一个清漆数据库监听器,因此能够通知varnish禁止内容已更改的页面.它发送了一个带有一些正则表达式的PURGE请求来禁止某些页面.
总而言之,有两种情况我得到了不幸的用户:
>页面的正常清漆TTL到期
>后端用户更改内容,这会向清除发送清除请求
在这两种情况下,我都有“不幸”的用户.在第二种情况下,后端用户通常在更改后检查页面,这可以缓解这种情况.但不一定.
尽管如此,对于第二种情况,我创建了一个解决方案(是的,我意识到这个问题始于寻找第一个案例的答案……我的问题很糟糕):
我没有发送清除请求,而是使用了Shanes建议并调整了VCL,以便我的varnish数据库侦听器可以发送一个特殊请求来获取hash_always_miss设置为true的页面.
使用当前的体系结构,我真的没有真正的异步请求,但在How do I make an asynchronous GET request in PHP?的帮助下,我能够为varnish创建一个GET请求,它不等待页面加载但是足够好触发varnish从后端获取页面并缓存它.
最终结果是数据库侦听器将请求发送到varnish,而当我查询特定页面时,它从未让我的请求“不吉利”,但一旦varnish从后端完全取出页面(这可能在300ms到2s之间)突然间在那里.
我还必须找到一个解决方案,当正常的TTL耗尽时如何避免同样的问题,但我想解决方案也和Shane建议完全一样:使用wget来触发hash_always_miss,我只需要足够聪明才能获得我要刷新的页面列表.