cd /var/tmp wget http://repo.varnish-cache.org/source/varnish-3.0.3.tar.gz tar xzf varnish-3.0.3.tar.gz cd varnish-3.0.3 sh autogen.sh sh configure make make test make install
backend default { .host = "127.0.0.1"; .port = "80"; }
/usr/local/sbin/varnishd -f /usr/local/etc/varnish/default.vcl ↪-a :6081 -P /var/run/varnish.pid -s malloc,256m
/usr/bin/pgrep -lf varnish
/usr/local/bin/varnishlog /usr/local/bin/varnishstat
GET -Used http://localhost:6081/
在這裡GET命令的選項無所謂。需要注意的是varnish返回的響應,varnish會增加三個相應頭信息,分別是“X-Varnish”、 “Via”和“Age”。這些頭信息在Varnish的處理過程中非常有用。X-Varnish頭信息的後面會有一個或兩個數字,如果是一個數字,就表明 varnish在緩存中沒有發現這個請求,這個數字的含義是varnish為這個請求所做的標記ID。如果X-Varnish後是兩個數字,就表明 varnish在緩存中命中了這個請求,第一個數字是請求的標識ID,第二個數字是緩存的標識ID。“Via”頭信息表明這個請求將經過一個代理。 “Age”頭信息標識出這個請求將被緩存多長時間(單位:秒)。首次請求的“Age”為0,後續的重復請求將會使Age值增大。如果後續的請求沒有是 “Age”增加,那就說明varnish沒有緩存這個響應的結果。
現在來看看 varnishstat 命令啟動執行的情況,如下圖所示:
圖2. varnishstat 命令
最重要的是 cache_hit 和 cache_miss 這兩行。如果沒有任何命中,cache_hits 不會顯示。當越來越多的請求進來,計數器會不斷更新以反應新的命中數和未命中數。
接下來看看 varnishlog 命令:
圖3. varnishlog 命令
上圖顯示varnish接受請求並作出響應的內部細節,下面是varnish官方文檔中的解釋:
第一列是一個亂數,用來標識當前請求。第一列數字相同的行屬於一HTTP請求序列。第二列是日志信息的標簽,所有的日志信 息會分類標記,以“Rx”開頭的為接收的數據,以“Tx”開頭的為發送的數據。第三列表示數據在客戶端,vainish和web服務器之間的傳輸狀態。第 四列是被日志記錄的數據。
varnishlog命令有很多的選項可以在查詢時使用。強烈推薦在排錯或測試時使用varnishlog。可以閱讀varnish的man page來查看這個命令的詳細使用情況。下面是一些使用的例子。
顯示varnish和客戶端之間的通信(忽略後端web服務器):
/usr/local/bin/varnishlog -b
顯示varnish接收到的HTTP頭信息(既有客戶端請求的,也有web服務器響應的):
/usr/local/bin/varnishlog -c -i RxHeader
只顯示web服務器響應的頭信息:
/usr/local/bin/varnishlog -Dw /var/log/varnish.log
從/var/log/varnish.log中讀取所有日志信息
kill `cat /var/run/varnish.pid`
這個命令會從/var/run/varnish.pid中讀取varnish的主進程的PID,並給這個進程發送TERM信號,從而關閉varnish。
現在通過上述命令,我們可以控制varnish的啟動和關閉,可以檢查緩存的命中情況,下一個問題是varnish到底緩存了什麼,會存多久?
varnish的默認緩存策略是偏向保守的(可以通過配置改變)。它默認只緩存get請求和HEAD請求。不會緩存帶有Cookie和認證信息的請 求,也不會緩存帶有Set-Cookie或者有變化的頭信息的響應。varnish也會檢查請求和響應中的Cache-Control頭信息,這個頭信息 中會包含一些選項來控制緩存行為。當Cache-control中Max-age的控制和默認策略沖突時,varnish不會單純的根據Cache- control信息就改變自己的緩存行為。例如:Cache-Control: max-age=n,n為數字,如果varnish收到web服務器的響應中包含max-age,varnish會以此值設定緩存的過期時間(單位: 秒),否則varnish將會設置為參數配置的時間,默認為120秒。
注意:
varnish的默認配置可以適應多數情況。例如,默認的default_ttl緩存過期時間是120秒。配置文件的詳細解釋可以閱讀 varnishd的man page。如果你想改變某些默認設置,一種方式是通過命令行varnishd加上-p參數,這將重啟varnishd,並清空緩存。另外一種方式是使用 varnish的管理接口,要使用varnish的管理接口需要以-T參數啟動varnish,這個參數指定了,varnish管理接口的監聽端口。然後 使用varnishadm命令連接到varnish的管理接口上,然後實時的查詢varnish的運行參數,或者更改新的參數,這些都不需要重啟 varnish。
想要了解詳細的情況,可以參閱varnishd、varnishadm和varnish-cli的man page。
一般情況下我們會改變varnish的緩存行為,定制自己的緩存策略。可以將配置寫入默認的default.vcl文件,VCL是varnish的配置文件的格式,像一種簡單的腳本語言。可以通過vcl的man page來了解詳細的格式,推薦閱讀。
在修改default.vcl配置之前,我們先來看一下varnish處理http請求的一個完整過程。我們將之成為一個請求/響應周期 (request/response cycle)。這個過程始於varnish收到客戶端的請求,varnish將檢查這個請求,並將其標記存儲,接下來varnish將根據一定的策略決定 是將這個請求直接轉發,還是檢查緩存。如果是第一種情況,varnish會將請求直接轉發到後端的服務器上,並且將服務器的響應返回給你客戶端。如果是第 二種情況,varnish會進行一個緩存查詢的過程,如果緩存命中,varnish會將緩存中結果返回給客戶端,如果緩存中沒有,varnish會將此請 求轉發給後端的服務器,並將服務器的響應先進行緩存,然後再轉發給客戶端。
了解完varnish對請求和響應處理的過程之後,我們來討論一下如何改變varnish的緩存策略。varnish有一系列的子功能來完成上述處 理過程,每一個子功能完成處理過程的一個部分。每一個子功能的執行結果傳遞給下一個子功能。所以我們可以通過改變子功能的返回值來改變varnish的處 理動作。每一個子功能都在default.vcl中有一個默認定義,可以通過改變這些值來定制varnish的功能。
Varnish 子程序
varnish的子程序在default.vcl中有默認的配置,如果你重新配置了某一個功能,並不意味著默認的動作一定不會執行。一般情況下,如 果你重新配置了某一個功能,但是沒有返回值,varnish將會執行默認的動,因為所有的varnish子程序都會有一個返回值。這可以看作 varnish的一種容錯機制。
第一個子程序是“vcl_recv”,在姐收到完整的客戶端請求後開始執行這個子程序,可以通過修改req對象來改變默認的請求處 理,varnish根據返回值決定處理方式。比如,返回:pass,將使varnish直接轉發請求到web服務器,返回:lookup,將使 varnish檢查緩存。
下一個子程序是vcl_pass。如果在vcl_recv中返回了“pass”,將執行vcl_pass。vcl_pass有兩種返回值,pass:繼續轉發請求到後端web服務器。restart:將請求重新返回給vcl_recv。
vcl_miss和vcl_hit將會根據varnish的緩存命中情況來執行。vcl_miss的執行有兩種情況,一是從後端服務器獲取響應結 果,並且在本地緩存(fetch),二是從後端獲取到響應,但本地不緩存(pass)。如果varnish緩存命中,將會執行vcl_hit,會有兩個選 擇,一個直接將緩存的結果返回給客戶端(deliver),二是丟棄緩存,重新從後端服務器獲取數據(pass)。
當從後端服務器獲取到數據之後,將會執行vcl_fetch過程,在這裡可以通過beresp對象來訪問響應數據,返回兩種處理結果;deliver:按計劃將數據發送給客戶端,restart,退回這個請求。
在vcl_deliver子程序中,可以將響應結果發送給客戶端(deliver),結束這個請求,同時根據不同情況決定是否緩存結果。也可以返回“restart”值,來重新開始這個請求。
如前所述,通過default.vcl來控制varnish的緩存策略,通過子程序的返回值來控制varnish的動作。子程序的返回值可以基於 req和resp對象,也可以基於客戶端對象,服務端對象或者後端服務器對象。但在子程序處理過程中,上述數據對象並非一直都可用。另外要注意子程序的返 回值會有一定的限制范圍,一個難點就是記住在什麼時候,哪個子程序中什麼數據對象是可用的,合法的返回值有哪些。為了讓這個問題更清晰一些,下面是一張表 格,可以在修改配置的時候快速參考:
表1. 各子程序中各數據對象的可用情況.
表2. 各子程序的合法返回值.
注意:
請仔細閱讀vcl的文檔來了解相關子程序,返回值以及可用的數據對象。
下面是一些實際的例子:
修改HTTP請求的 Host 頭信息:
sub vcl_recv { if (req.http.host ~ "^www.example.com") { set req.http.host = "example.com"; } }
你可以通過 req.http.host來訪問請求的HTTP host頭信息,類似的,你可以通過req.http訪問所有的HTTP頭信息。“~”符表示相等的意思,後面是一個正則表達式. 如果匹配上,會通過set關鍵字和“=”賦值操作,將hostname改為"example.com".修改hostname的一個作用是防止重復的緩 存。 因為varnish會通過hostname和URL來判斷緩存匹配情況,所以hostname應該被修改為統一的形式。
下面是默認 vcl_recv 子程序的一個片段:
sub vcl_recv { if (req.request != "GET" && req.request != "HEAD") { return (pass); } return (lookup); }
這是默認的vcl_recv配置文件的片段,在這個配置中如果發現請求不是GET或者HEAD,varnish將會直接pass這個請求,並且不會緩存這個請求的響應,如果是GET或HEAD,將會到緩存中進行查找。
匹配特定的URL,移除請求中的Cookie信息:
sub vcl_recv { if (req.url ~ "^/images") { unset req.http.cookie; } }
這個是varnish網站上的例子,如果發現請求的URL以"/images"開始,varnish會將其中的Cookie信息移除。當在cookie中設置不緩存當前響應時,varnish可以通過移除Cookie,來緩存這個響應。
在對圖片文件的響應頭中中移除set-Cookie:
sub vcl_fetch { if (req.url ~ ".(png|gif|jpg)$") { unset beresp.http.set-cookie; set beresp.ttl = 1h; } }
這個是varnish網站上的另一個例子。接收到web服務器的返回結果後會觸發vcl_fetch處理過程。當從web服務器接收到新的數據 後,beresp中保存web服務器返回的響應信息,req中是本次請求的信息。如果本次請求的文件是圖像文件,varnish會將響應頭信息中的 “Set-Cookie”移除,並且將緩存的時間設置為1小時(帶有Set-Cookie的響應,varnish不會緩存)。
現在我們想朝響應信息中增加一個"X-Hit"的頭信息,當緩存命中的時候,這個值為1,未命中的時候為0。根據上文,判斷緩存命中的最簡單的辦法 是在vcl_hit中。當緩存命中是會調用vcl_hit,因此可以考慮在vcl_hit中設置這個頭信息,但從上文表1中我們看到,vcl_hit裡 beresp和resp都是不可用的。一個可行的辦法就是在請求中設置裡一個臨時頭信息,然後在後續的處理過程中真正進行設置。下面我們看一下這個問題是 如何解決的:
在響應頭信息中增加“x-hit”:
sub vcl_hit { set req.http.tempheader = "1"; } sub vcl_miss { set req.http.tempheader = "0"; } sub vcl_deliver { set resp.http.X-Hit = "0"; if (req.http.tempheader) { set resp.http.X-Hit = req.http.tempheader; unset req.http.tempheader; } }
上述vcl_hit和vcl_miss中設置了一個臨時的請求頭信息,來標識出緩存的命中情況。真正的處理過程在vcl_deliver裡,首先默 認設置x-hit為0,然後根據請求裡的臨時頭信息判斷緩存的命中情況,並且依此更新剛才設置的x-hit默認值,最後刪除此臨時頭信息。之所以選擇在 vcl_deliver裡來進行處理,是因為在響應信息返回給客戶端之前,只有在vcl_deliver中才可以訪問resp對象。
下面我們看一個針對此問題錯誤的解決辦法:
增加“x-hit”頭信息(錯誤的方法):
sub vcl_hit { set req.http.tempheader = "1"; } sub vcl_miss { set req.http.tempheader = "0"; } sub vcl_fetch { set beresp.http.X-Hit = "0"; if (req.http.tempheader) { set beresp.http.X-Hit = req.http.tempheader; unset req.http.tempheader; } }
在vcl_fetch裡修改服務器返回的信息(beresp),但這並不是最終發送給客戶端的數據。上述配置貌似正確,其實隱含了一個大BUG。首 次請求當緩存未命中時,web服務器的響應被標上'x-hit'為0,然後送到vcl_fetch處理,並被緩存在本地。但當後續請求緩存命中 時,vcl_fetch過程不會被執行,結果就導致所有的緩存命中的響應都帶有x-hit=0的標記。這是在配置varnish時需要特別注意的一類問 題。
避免這些問題的辦法是熟練掌握上述的表1的內容,並且在實際工作中多做測試。
下面的配置可以讓varnish將所有的數據緩存一個小時(不建議在真實環境中使用)
sub vcl_recv { return (lookup); } sub vcl_fetch { set beresp.ttl = 1h; return (deliver); }
在上述配置中重寫了vcl_recv和vcl_fetch兩個過程。需要注意的是:如果vcl_fetch不返回“deliver”,varnish將會繼續執行默認的處理過程,就不會有想要的效果了。
一旦varnish運行生效之後,你可以通過一些負載測試工具來測試性能的改善。我通常使用的測試工具是apache自帶的ab,可以從apache的安裝包裡找到,或者通過一些第三方的包管理器進行安裝。可以在apache的網站上找到ab的使用文檔。
在下面的測試例子中,apache2.2監聽在80端口,varnish監聽在6081端口。用來做測試的頁面是一個非常簡單的perl CGI腳本,只輸出一個單行的HTML文件。通過訪問相同的URL來測試apache和varnish的不同表現。為避免網絡因素的影響,所有的測試都在 本機執行。測試中使用的ab選項非常簡單,也可以試著去改變這些選項,看看是什麼結果。
首先進行一個1000次的請求(n=1000),並發數量1個(c=1).
先測試apache:
ab -c 1 -n 1000 http://localhost/cgi-bin/test
圖 4. Apache測試結果
再測試varnish:
ab -c 1 -n 1000 http://localhost:6081/cgi-bin/test
圖 5. varnish測試結果
ab的測試輸出裡包含很多信息,最基本的性能指標有“Time per request”和“Requests per second(rps)”。
從上述測試結果來看,apache的每個請求在1ms以上(780rps),而varnish在0.1ms(7336rps)比apache高了10倍。
從這個測試結果說明varnish的速度比apache快,至少在當前環境下是這樣。可以嘗試改變ab的選項來進行不同的測試,例如改變並發訪問數量。
系統負載和磁盤IO( %iowait)
系統負載是反映CPU運行狀況的指標,通常情況下系統中每個CPU核心的負載應該在1.0以下。如果你的系統中有4個CPU核心,理想的系統負載應該在4.0以下。
磁盤的%iowait反映每個CPU時間片內系統的輸入輸出(I/O)狀況。%iowait指標較高表示磁盤IO成為了系統瓶頸會拖慢整體的速度。比如,如果收到的每個請求都需要讀取100個文件或者更多,這將會導致%iowait迅速升高然後成為系統性能的瓶頸。
測試的時候除了關注系統的響應時間之外,還要看系統資源的使用情況。當測試請求持續很長時間時,我們比較一下兩者的系統資源使用情況。監控的指標就 是系統的負載(system load)和磁盤IO(%iowait)。系統負載可以從top命令裡查看,%iowait可以從iostat命令看到。在測試過程中需要同時關注這兩個 指標,我們打開兩個終端分別運行top和iostat。
運行iostat,2秒更新一次:
iostat -c 2
運行top:
/usr/bin/top
現在就可以做測試了。因為要看長時間持續請求的狀況下服務器的性能表現(至少要在1到10分鐘),所以需要在ab的選項裡加大請求次數和並發數量。
使用ab對Apache進行測試:
ab -c 50 -n 100000 http://localhost/cgi-bin/test
圖 6. Apache 下系統壓力測試流量記錄
使用ab測試Varnish:
ab -c 50 -n 1000000 http://localhost:6081/cgi-bin/test
圖 7. Varnish下系統壓力測試流量記錄
首先對比響應時間,雖然截圖上沒有直接顯示時間,但是我們可以從ab結束的時間計算出來,apache是23ms每次請求 (2097rps),varnish是4ms每次請求(12099rps)。最大的差異是平均負載,Apache使系統的負載達到了12,使用 varnish時則一直保持在0~0.4。在從apache切換到varnish做測試時,甚至要等上幾分鐘,系統負載才能回復正常。最好在非生產環境下 用比較空閒的機器做這些測試。
盡管真實環境中的web服務器有很多個性化的配置和需求,但是vanish一般都可以幫助你的web服務器提高性能並且降低負載。
轉自:http://www.oschina.net/translate/speed-your-web-site-varnish