最近我们在我们的服务器上configuration了Varnish,它已经成功安装了,但是我们注意到,如果我们在多个浏览器中打开任何页面,Varnish向Apache发送请求无关紧要。 如果我们在每个浏览器上刷新两次,它会创build相同页面的重复副本。
究竟应该发生什么:
如果任何页面被Varnishcaching,则当我们在浏览器中打开同一页面时,后续请求应该从Varnish本身提供,或者我们从不同的IP地址打开该页面。
以下是我的default.vcl文件
backend default { .host = "127.0.0.1"; .port = "80"; } sub vcl_recv { if( req.url ~ "^/search/.*$") { }else { set req.url = regsub(req.url, "\?.*", ""); } if (req.restarts == 0) { if (req.http.x-forwarded-for) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } } if (!req.backend.healthy) { unset req.http.Cookie; } set req.grace = 6h; if (req.url ~ "^/status\.php$" || req.url ~ "^/update\.php$" || req.url ~ "^/admin$" || req.url ~ "^/admin/.*$" || req.url ~ "^/flag/.*$" || req.url ~ "^.*/ajax/.*$" || req.url ~ "^.*/ahah/.*$") { return (pass); } if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") { unset req.http.Cookie; } if (req.http.Cookie) { set req.http.Cookie = ";" + req.http.Cookie; set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1="); set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.Cookie == "") { unset req.http.Cookie; } else { return (pass); } } if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" && req.request != "OPTIONS" && req.request != "DELETE") {return(pipe);} /* Non-RFC2616 or CONNECT which is weird. */ if (req.request != "GET" && req.request != "HEAD") { return (pass); } if (req.http.Accept-Encoding) { if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") { # No point in compressing these remove req.http.Accept-Encoding; } else if (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } else if (req.http.Accept-Encoding ~ "deflate") { set req.http.Accept-Encoding = "deflate"; } else { # unknown algorithm remove req.http.Accept-Encoding; } } return (lookup); } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Varnish-Cache = "HIT"; } else { set resp.http.X-Varnish-Cache = "MISS"; } } sub vcl_fetch { if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) { set beresp.ttl = 10m; } if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") { unset beresp.http.set-cookie; } set beresp.grace = 6h; } sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (hash); } sub vcl_pipe { set req.http.connection = "close"; } sub vcl_hit { if (req.request == "PURGE") {ban_url(req.url); error 200 "Purged";} if (!obj.ttl > 0s) {return(pass);} } sub vcl_miss { if (req.request == "PURGE") {error 200 "Not in cache";} }
解
陷阱 – 不同:用户代理
某些应用程序或应用程序服务器发送Vary:User-Agent及其内容。 这指示Varnish为用户代理的每个变体caching单独的副本。 有很多。 即使是同一浏览器的单个补丁级别,也会根据它们正在运行的操作系统生成至less10个不同的User-Agent标头。
所以,如果你真的需要基于User-Agent的变化,一定要正常化标题或命中率将遭受严重。 使用上面的代码作为模板。
https://www.varnish-cache.org/docs/3.0/tutorial/vary.html#tutorial-vary
解决方法
一种解决方法是做我们所说的“User-Agent-Washing”,其中Varnish将Useragent重写为后端真正关心的不同变体的handfull,如下所示:
sub vcl_recv { if (req.http.user-agent ~ "MSIE") { set req.http.user-agent = "MSIE"; } else { set req.http.user-agent = "Mozilla"; } }
首先,清漆不可能caching2个URL的副本。
现在,我不知道命中/小姐检查,但是当我需要检查,我会在Firefox中做到这一点,并使用Firebug的。
我将打开萤火虫,并打开网站。
在这里,它会显示每个页面/图像的年龄,如附图所示。
如果年龄在逐渐增加,那么对于我来说,Varnish工作得很好。
而且我可以看到,它也适用于您的网站。

这是什么帮助我解决了这个问题:
取消注释注释掉或删除形成vch_hash函数的行并重新启动清漆。 vcl_hash用于创build特定的高速caching,例如为用户或会话或特定的IP地址。 如果您希望页面(caching后)caching,则可以使用vcl_hash函数。
以防万一,在testing环境中进行testing。
HTH。
编辑(澄清)
选项1 :
通过在每一行的开头加上“#”号来注释掉这些行。 所以这些线
sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (hash); }
会成为:
#sub vcl_hash { # hash_data(req.url); # if (req.http.host) { # hash_data(req.http.host); # } else { # hash_data(server.ip); # } # return (hash); #}
以#开始的行被varnish忽略。
选项2 :
或者,您可以一起删除上述行。 最终的结果是一样的。