如果您在同一个 URL 上提供不同的内容类型,您可能需要告诉 Varnish 相应地对缓存进行分区。
事实上,Varnish 并没有什么特别之处,它的行为与其他代理一样。如果他们看到的 URL 没有指定资源缓存应如何分区的信息,那么无论是 JSON 还是常规请求,第一个请求都将被缓存并以相同的方式提供服务,而与请求类型无关。
所以你需要告诉 Varnish 如何为资源分区缓存。
“变化”标题
对于其他代理来说,最直接和“HTTP”兼容的方式是Vary response 标头。
它告诉代理缓存(在本例中为 Varnish)根据来自客户端的标头值对资源进行分区、变化缓存。
例如客户端发送标头 X: some-value 并且您的应用发送标头 Vary: X 是为了使缓存在 X的不同值之间有所不同>.
对于 Varnish 3,有一个带有 Accept-Encoding 的示例。
文章详细介绍了Vary 的实现挑战——不同的客户端可能会为不同的标头发送完全不同的值,从而导致缓存严重分区。因此,您通常希望将可变标头的值标准化为一组已知的预期值。
在您的情况下,您想要改变(并规范化)Accept header。所以类似于(在vcl_recv 程序中):
if (req.http.Accept) {
if (req.http.Accept ~ "application/json") {
set req.http.Accept = "application/json";
} else {
set req.http.Accept = "text/html";
}
}
接下来,您需要让您的应用实际发送Vary: Accept(在您的应用源文件中)。或者,如果修改应用程序源文件不可行,您可以抛出一些 Varnish VCL:
sub vcl_fetch {
if (!beresp.http.Vary) { # no Vary at all
set beresp.http.Vary = "Accept";
} elseif (beresp.http.Vary !~ "Accept") { # add to existing Vary
set beresp.http.Vary = beresp.http.Vary + ", Accept";
}
}