我正在为电子商务平台开发一个缓存系统,该系统将使用反向代理进行缓存。我计划使用适当的 HTTP/1.1 标头来处理失效问题。也就是说,我将在第一次生成内容时设置 ETag,并在应用程序中缓存该 ETag 值。Cache-Control 标头将指定“must-revalidate”,因此代理应在后续使用 ETag 的请求中设置 If-None-Match 标头。应用程序将查找缓存的 ETag 值,如果匹配,它将发送 304 响应,否则它将生成完整的 200 响应。
我希望使用 nginx,但我不能确定它是否支持 ETag(文档表明它不支持,但也许它们已经过时了?)。Varnish 是另一个选择,但我也不确定。
哪些反向代理服务器完全支持 ETag?我希望它能够缓存多个版本,这样我就可以进行拆分测试等操作,而无需禁用缓存。也就是说,HTTP/1.1 规定客户端可以发送带有多个 ETag 值的 If-None-Match,服务器应该响应匹配的 ETag(如果有)。如果反向代理保留多个副本而不仅仅是最后看到的值,并让服务器在每个请求中指定要使用哪个副本,那就太理想了。
答案1
我刚刚检查了 Varnish 源代码,尽管它支持If-Modified-Since
和If-None-Match
标头,但不支持。must-revalidate
中Cache-Control
唯一支持的属性Cache-Control
是max-age
和s-max-age
。
参考:
bin/varnishd/cache/cache_rfc2616.c
在RFC2616_Do_Cond()bin/varnishd/cache/cache_rfc2616.c
在RFC2616_Ttl()include/tbl/http_headers.h
答案2
答案3
如果我错了,请纠正我,我知道这是一篇旧帖子 - 但我想为新路人发表评论。我相信在使用 ETag 时,反向代理缓存不会像你想象的那样有帮助。
验证缓存机制使用原始服务器来验证请求中的 ETag(或最后修改日期)是否仍然有效(与资源 etag 匹配或不匹配,取决于所使用的标头,或者自请求中给出的日期以来是否已被修改)。
这意味着反向代理缓存(例如 Varnish)仍会将该请求传递到原始服务器。它可能会响应该请求,而不是让服务器处理它,但您没有节省往返原始服务器的时间。
浏览器可以缓存响应并在任何情况下处理 304 响应,因此用户的私有缓存可能比使用反向代理更适合处理这个问题(YMMV,特别是在规模上,当然取决于您的使用情况。我不想对你的应用程序做出假设)。
从规格来看13.3:
当缓存中有过期条目,而缓存想要将其用作对客户端请求的响应时,它首先必须与原始服务器(或可能是具有新响应的中间缓存)进行检查,以查看其缓存条目是否仍然可用。我们称之为“验证”缓存条目。由于如果缓存条目良好,我们不想支付重新传输完整响应的开销,如果缓存条目无效,我们不想支付额外往返的开销,因此 HTTP/1.1 协议支持使用条件方法。
然后注意13.3.4:
HTTP/1.1 缓存代理在收到包含 Last-Modified 日期和一个或多个实体标签作为缓存验证器的条件请求时,不得向客户端返回本地缓存的响应,除非该缓存响应与请求中的所有条件标头字段一致。
因此,Varnish 可以为您返回响应,但您仍需要往返服务器。如果您可以使用 APC 或 memcache 等应用缓存,那么这对您来说可能还是值得的。然而,验证缓存通常比节省服务器资源更有利于节省带宽。
验证缓存最好留给客户端(浏览器或 API 代码)。
使用过期模型进行缓存是反向代理缓存真正发挥作用的地方。这让您完全跳过访问原始服务器。使用Expires
、、Cache-Control
等Date
是反向代理缓存的最佳机制(再次强调,在我看来),因为缓存可以返回响应(假设响应不是过时的),而无需访问原始服务器。
答案4
到目前为止,我认为还没有完全支持此 HTTP 规范的代理。所以大约一年前,我决定使用 Node.js 和 MongoDb 编写自己的代理。