HTTP Vary
HTTP Vary不是一个简单的概念,它是迄今为止最被误解的http头。
大量的响应头告诉客户端一些关于被传递的http对象信息。客户端可以基于其偏好,请求http对象的不同变体。他们的偏好可能会覆盖一些东西,例如encoding和language。当客户端更喜欢英式英语的话可以通过Accept-Language: en-uk
来传递。缓存需要将不同的种类区分开,这是通过http响应头Vary来实现的。
当后端服务器返回Vary: Accept-Language
,它告诉varnish,它需要对每一个来自客户端的Accept-Language区分对待,并缓存不同的版本。
当两个客户端分别声明他们接受的语言是“en-us, en-uk”和“da, de”,varnish将会缓存页面两个不同的版本,如果后端标识varnish需要区分Accept-Language头的话。
但是你需要注意的是,Vary需要完全匹配。因此,对于"en-us, en-uk"和"en-us,en-uk"两个头varnish将会创建并保存两个不同的版本。仅仅是因为其中一个版本中间多了一个空格。
为了在使用Vary的同时获得较高的命中率,关键是要对后端的header标准化。哪怕有一点不同,就会导致不同的缓存。
下面的VCL代码将会对Accept-Language格式标准化:
if (req.http.Accept-Language) {
if (req.http.Accept-Language ~ "en") {
set req.http.Accept-Language = "en";
} elsif (req.http.Accept-Language ~ "de") {
set req.http.Accept-Language = "de";
} elsif (req.http.Accept-Language ~ "fr") {
set req.http.Accept-Language = "fr";
} else {
# unknown language. Remove the accept-language header and
# use the backend default.
unset req.http.Accept-Language
}
}
Vary格式化错误
当它格式化Vary头失败时,varnish就会返回503错误。或者客户端的头大小超过的65k,在这种情况下SLT_Error日志会被增加。
陷阱——Vary: User-Agent
一些程序或者程序服务器会与内容一起发送Vary: User-Agent
头。这就会指示varnish对每个不同的User-Agent缓存不同的内容。即使是相同的浏览器,基于不同的系统、不同的版本也会有至少有10个不同的User-Agent头。
所以,如果你真的想要基于User-Agent去区分不同的内容,你最好先对头信息进行格式化,否则你的命中率将会很差劲。可以使用上面的代码作为模版进行修改。