我正在缓存动态生成的页面(PHP-FPM,NGINX),并在它们前面涂上清漆,效果很好。
但是,一旦达到缓存超时,我将看到:
- 新客户请求页面
- 清漆识别缓存超时
- 客户等待
- 清漆从后端获取新页面
- 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发送,听起来很相似,但与我要执行的操作不完全相同。)
解
Shane Madden的回答包含了解决方案,但我没有立即意识到。我没有在问题中包含另一个细节,因为我认为这不相关,但实际上是相关的。
我当前正在使用的CMS解决方案具有清漆数据库侦听器,因此可以通知清漆禁止内容已更改的页面。它发送了PURGE
一些正则表达式来禁止某些页面的请求。
综上所述,有两种情况下我的用户很不幸:
- 页面的普通清漆TTL过期
- 后端用户更改内容,这会将清除请求发送到清漆
在这两种情况下,我都有“不幸”的用户。在第二种情况下,后端用户通常会在页面更改后检查页面,从而缓解了这种情况。但不一定。
但是,对于第二种情况,我创建了一个解决方案(是的,我意识到这个问题首先是为第一种情况寻求答案……而我本人制定得不好的问题):
我没有发送清除请求,而是使用Shanes建议并调整了VCL,以便我的清漆数据库侦听器可以发送特殊请求以获取hash_always_miss
设置为的页面true
。
使用当前的体系结构,我真的没有做一个真正的异步请求的奢侈,但是借助“ 如何在PHP中发出异步GET请求”的帮助?我能够设计一个GET请求来清漆,它不等待页面加载,但是足以触发清漆从后端获取页面并缓存它。
最终结果是数据库侦听器将请求发送给varnish,而当我轮询特定页面时,它从未使我的请求“很不幸”,但是一旦varnish完全从后端获取了页面(范围从300ms到2s),突然在那里。
我还必须找到一种解决方案,当普通TTL用尽时如何避免相同的问题,但是我猜该解决方案也与Shane建议的完全一样:使用wget触发hash_always_miss
,我只需要足够聪明即可获取列表我必须刷新的页面数。