本节集中解决如何调优varnish server,同时如何使用varnish优化你的web站点.html
一共有三小节.第一小节你应该想到varnish的各类工具和功能,下一小节如何从cache中清除已经缓存的内容.清除内容是一项基本功能,由于它容许给缓存的对象增长 TTL.TTL越大varnish保持在缓存中的时间越久,这意味着varnish处理更多的请求,只将少部分的请求传递到相对较慢的后端.前端
最后一小节,处理web内容的压缩.当从后端得到内容时varnish能够压缩它,而后传递被压缩后的内容.这种方式能够减小客户如今内容的时间,从而提升你的web站点的性能.linux
如今,varnish已经启动和运行,你能够经过varnish访问您的Web应用程序。除非你的应用程序是专门工做在网络加速器以后的,你可能须要在varnish的配置或应用程序上作一些改变,以提升varnish的命中率。web
varnish不会缓存你的数据,除非它是绝对确定操做是安全的。所以,对于你为了了解varnish如何决定是否和如何来缓存页面,咱们会经过一些工具引导你,你能够找到一些工具便于理解在varnish的配置中发生了什么。正则表达式
注意,你须要一个工具来查看穿越varnish和后端之间的HTTP头。在varnish服务器,最简单的方法是使用varnishlog和varnishtop,但有时客户端工具也是有意义的。这些工具是咱们经常使用 的chrome
Tool: varnishtopexpress
可使用varnishtop来找出什么url正在被命中。varnishtop -i BereqURL 是基本的命令,向你展现varsnih发送到后端的top请求。你能够在Statistics 中查看varnishtop 用法的其余列子。后端
Tool: varnishlog浏览器
当你找出一个频繁发送到后端的URL,你可使用varnishlog查看该请求。varnishlog -q 'ReqURL ~ "^/foo/bar"' 向你展现来自客户端匹配到/foo/bar的请求。缓存
关于varnishlog如何工做的更多信息请查看Logging in Varnish 或者产看varnishlog的man手册。
扩展的http头,http://www.varnish-cache.org/trac/wiki/VCLExampleHitMissHeader
Tool: lwp-request
lwp-request 是Perl www库中的工具。能够发送请求同时向你展现结果的基本程序。 该工具主要是查看http响应头。不少工具均可以实现。好比linux自带的curl工具。
# curl -I http://vg.no/ HTTP/1.1 301 Moved Permanently Server: Apache/2.2.15 (CentOS) X-VG-WebServer: vgphoenix-web-02 Location: http://www.vg.no/ Content-Type: text/html; charset=iso-8859-1 X-VG-SolveMe: uggc://jjj.it.ab/ynxfrgngg.ugzy Date: Mon, 20 Jul 2015 03:28:46 GMT Connection: keep-alive X-Cache: HIT:40 Vary: Accept-Encoding,User-Agent X-VG-WebCache: hmg9-varnish-01 X-Age: 46 Age: 0
还firefox的firebug工具,chrome自带的工具均可以查看。
默认状况,varnish不缓存从后端响应的http头中带有Set-Cookie的对象。若是客户端发送的请求带有Cookie header,varnish将忽略缓存,直接将请求传递到后端。
这多是多度保守。大量站点使用Google Analytics来分析他们的流量,GA设置cookie信息来跟踪你。该cookie被客户端的js所使用,服务端不感兴趣的。
Cookies from the client
对于大量的web应用彻底清楚cookie是有意义的,除非你指定不须要忽略cookie的web站点的部分。
在vcl_recv中的vcl片断将忽略cookie,除非你访问的url中匹配到/admin/
if (!(req.url ~ "^/admin/")) { unset req.http.Cookie; }
至关简单。然而若是你须要作些复杂的事情,像移除几个cookie中的一个,这就变得困难了。不幸的是,varnish没有一些好的工具来操控cookies。咱们不得不使用正则表达式来实现。若是你熟练正则表达式你将理解到发生了什么,否则咱们仍是建议你先看看pcrepattern(PCRE - Perl-compatible regular expressions),或则查看丰富的在线文档。
咱们来看看Varnish Software(VS) 的例子。很是简明的设置,varnish cache在前端,后端使用Drupal-based。VS使用一些跟踪谷歌分析的cookie还有一些其余类似的工具。全部的cookie变成一个集合,被js所使用。varnish和Drupal都不须要查看这些cookie,同时自从客户端发送cookie到varnish,varnish将终止正在缓存的页面,varnish须要在VCL中丢弃没必要要的cookie。
下面的VCL中咱们丢弃如下划线开始的全部cookie:
# Remove has_js and Google Analytics __* cookies. set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", ""); # Remove a ";" prefix, if present. set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
下面的例子,咱们移除全部的cookie除了叫作COOKIE1和COOKIE2,你会惊奇的发现,如此完美:
sub vcl_recv { 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, ";(COOKIE1|COOKIE2)=", "; \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; } } }
一个稍微简单的例子。使用相同的功能,能几乎完成。从“other”cookie中过滤出“the one”咱们须要的cookie,复制它给header中的另外一个,而后复制回请求中,再删除原来的cookie header。验证请求的正确性。:
sub vcl_recv { # save the original cookie header so we can mangle it set req.http.X-Varnish-PHP_SID = req.http.Cookie; # using a capturing sub pattern, extract the continuous string of # alphanumerics that immediately follows "PHPSESSID=" set req.http.X-Varnish-PHP_SID = regsuball(req.http.X-Varnish-PHP_SID, ";? ?PHPSESSID=([a-zA-Z0-9]+)( |;| ;).*","\1"); set req.http.Cookie = req.X-Varnish-PHP_SID; unset req.X-Varnish-PHP_SID; }
在Varnish Cache Wiki 有更多varnish在VCL中能作什么的惊奇例子。
Cookies coming from the backend
使用默认设置的话,后端server若是设置了Set-Cookie头,varnish将不缓存该内容。一个hit-for-pass 的对象被建立。所以若是后端行为诡异同时设置些不须要的cookie,unset 'Set-Cookie'头,一切将变得ok。
Cache-Control
Cache-Control头通知缓存,如何处理该内容。Varnish关心' max-age '参数,而且是用它来计算一个对象的TTL。
所以,肯定你用max-ag设置了'Cache-Control'头。你能够看看Varnish Software的Drupalserver的响应。
$ curl -I http://www.varnish-software.com/|grep 'Cache-Control' Cache-Control: max-age=1209600
Age
Varnish 增长'Age'头来标明对象被varnish缓存多久。你可使用* varnishlog -I RespHeader:^Age*来从varnishlog筛选出Age。
Pragma
HTTP 1.0server可能发送Pragma: nocache 头。varnish忽略pragma头。你很容易增长对该pragma头的支持。 在vclbackendresponse:
if (beresp.http.Pragma ~ "nocache") { set beresp.uncacheable = true; set beresp.ttl = 120s; # how long not to cache this url. }
Authorization
若是varnish看到header中有'Authorization'头,它将pass请求。若是你不须要这个头,你能够unset。
Overriding the time-to-live (TTL)
有时候你的后端会抽下风。在varnish能够容易的重写TTL,而后你再修复你笨重的后端。 须要在VCL中指定想要设置的对象,而后设置'beresp.ttl'
sub vcl_backend_response { if (bereq.url ~ "^/legacy_broken_cms/") { set beresp.ttl = 5d; } }
Forcing caching for certain requests and certain responses
你的后端可能仍然是笨重的,且不能很好的工做,你可能想存放更多的资源到varnish。咱们建议你依赖尽量多的默认缓存规则。强制varnish在高速缓存中查找对象是很容易的,但它并非真正的建议。
Normalizing your namespace
有些站点是有许多域名的。 http://www.varnish-software.com/, http://varnish-software.com/ and http://varnishsoftware.com/ 都指向同一个站点。而varnish不知道他们是相同的。varnish会根据不一样的域名缓存同一个对象不一样的版本。你能够减缓这种状况,经过在webserver中配置redirect或者使用下面的VCL:
if (req.http.host ~ "(?i)^(www.)?varnish-?software.com") { set req.http.host = "varnish-software.com"; }
HTTP Vary 并非微不足道的概念。这是迄今为止最被误解的HTTP标头。
大量的响应头告诉客户端关于该HTTP对象是否该被传递。客户端能够基于他们的参数选择请求不一样的http对象。他们的参数选择包括像编码和域名。当客户端倾向于UK English时,经过Accept-Language: en-uk 代表。缓存须要保持不一样的版本,经过响应中的'Vary'头来实现。
当后端server被Vary:Accept-Language标示时,它告诉Varnish须要对每一个不一样的Accept-Language保存不一样的版本。
若是两个客户端分别接受"en-us, en-uk" 和 "da, de",同时若是后端标明不一样Accept-Language,varnish将缓存和提供两个不一样的版本。
请注意Vary头须要彻底匹配。所以若是Vary中是 "en-us, en-uk" 和"en-us,en-uk"(多个空格),varnish将保存同一个页面的两个副本。
得到搞得命中率的同时使用Vary,关键是标准化后端的header。记住,哪怕是有一点不一样,会致使不一样的缓存条目。
下面的vcl代码将标准化Accept-Language头,无论"en", "de" 或者 "fr",以这个优先顺序。
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 parse errors
若是varnish解析Vary头出错,将会返回503网络错误。或者客户端的头大小超过的65k. 在这种状况下SLT_Error日志会被增长。
Pitfall - Vary: User-Agent
user-Agent的陷阱。
一些应用或者应用服务器,把'Vary: User-Agent'随着内容一块儿发送。这个行为通知varnish缓存每一个'User-Agent'版本的单独副本。即时是同一个浏览器的单个补丁版本对于不一样的运行操做系统也至少有10中不一样的User-Agent。
若是你真的须要基于User-Agent多样化,必定要初始化标准化header或者你能忍受varnish的命中率。使用上述代码做为一个模板。