本節集中解決如何調優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的命中率。使用上述代碼做爲一個模板。