一:varnish簡介
Varnish是一款高性能的開源HTTP加速器,挪威最大的在線報紙 Verdens Gang 使用3臺Varnish代替了原來的12臺Squid,性能比以前更好
Varnish 的作者Poul-Henning Kamp是FreeBSD的內核開發者之一,他認爲現在的計算機比起1975年已經複雜許多。在1975年時,儲存媒介只有兩種:內存與硬盤。但現在計算機系統的內存除了主存外,還包括了CPU內的L1、L2,甚至有L3快取。硬盤上也有自己的快取裝置,因此Squid Cache自行處理物件替換的架構不可能得知這些情況而做到最佳化,但操作系統可以得知這些情況,所以這部份的工作應該交給操作系統處理,這就是 Varnish cache設計架構.
二:varnish設計機構圖
三:VCL 處理流程
Varnish 處理 HTTP 請求的過程大致分爲如下幾個步驟。
- Receive 狀態(vcl_recv)。也就是請求處理的入口狀態,根據 VCL 規則判斷該請求應該 pass(vcl_pass)或是 pipe(vcl_pipe),還是進入 lookup(本地查詢)。
- Lookup 狀態。進入該狀態後,會在 hash 表中查找數據,若找到,則進入 hit(vcl_hit)狀態,否則進入 miss(vcl_miss)狀態。
- Pass(vcl_pass)狀態。在此狀態下,會直接進入後端請求,即進入 fetch(vcl_fetch)狀態
- Fetch(vcl_fetch)狀態。在 fetch 狀態下,對請求進行後端獲取,發送請求,獲得數據,並根據設置進行本地存儲。
- Deliver(vcl_deliver)狀態。將獲取到的數據發給客戶端,然後完成本次請求
1) VCL 內置函數
vcl_recv 函數
用於接收和處理請求。當請求到達併成功接收後被調用,通過判斷請求的數據來決定如何處理請求。例如如何響應、怎麼響應、使用哪個後端服務器等。
此函數一般以如下幾個關鍵字結束。
pass:表示進入 pass 模式,把請求控制權交給 vcl_pass 函數。
pipe:表示進入 pipe 模式,把請求控制權交給 vcl_pipe 函數。
lookup:表示進入 lookup 模式,把請求控制權交給 lookup 指令處理,在緩存中查找被請求的對象,並且根據查找的結果把控制權交給函數 vcl_hit 或函數 vcl_miss。
error code [reason]:表示返回“code”給客戶端,並放棄處理該請求。“code”是錯誤標識,例如 200 和 405 等。“reason”是錯誤提示信息.
vcl_pipe 函數
此函數在進入 pipe 模式時被調用,用於將請求直接傳遞至後端主機,在請求和返回的內容沒有改變的情況下,將不變的內容返回給客戶端,直到這個連接被關閉。
此函數一般以如下幾個關鍵字結束。
error code [reason]。
pipe
vcl_pass 函數
此函數在進入 pass 模式時被調用,用於將請求直接傳遞至後端主機。後端主機在應答數據後將應答數據發送給客戶端,但不進行任何緩存,在當前連接下每次都返回最新的內容。
此函數一般以如下幾個關鍵字結束。
error code [reason]。
pass。
restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告
vcl_hash
當您想把一個數據添加到 hash 上時,調用此函數。
此函數一般以如下幾個關鍵字結束
vcl_hit 函數
在執行 lookup 指令後,在緩存中找到請求的內容後將自動調用該函數。
此函數一般以如下幾個關鍵字結束。
deliver:表示將找到的內容發送給客戶端,並把控制權交給函數 vcl_deliver。
error code [reason] 。
pass。
restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告
vcl_miss 函數
在執行 lookup 指令後,在緩存中沒有找到請求的內容時自動調用該方法。此函數可用於判斷是否需要從後端服務器獲取內容。
此函數一般以如下幾個關鍵字結束。
fetch:表示從後端獲取請求的內容,並把控制權交給 vcl_fetch 函數。
error code [reason] 。
pass。
vcl_fetch 函數
在後端主機更新緩存並且獲取內容後調用該方法,接着,通過判斷獲取的內容來決定是將內容放入緩存,還是直接返回給客戶端。
此函數一般以如下幾個關鍵字結束。
error code [reason]。
pass。
deliver。
esi。
restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告
vcl_deliver 函數
將在緩存中找到請求的內容發送給客戶端前調用此方法。
此函數一般以如下幾個關鍵字結束。
error code [reason]。
deliver。
restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告
vcl_error
出現錯誤時調用此函數。
此函數一般以如下幾個關鍵字結束。
deliver。
restart
2)工作流程概述
Varnish 與一般服務器軟件類似,分爲 master 進程和 child 進程。Master 進程讀入存儲配置文件,調用合適的存儲類型,然後創建 / 讀入相應大小的緩存文件,接着 master 初始化管理該存儲空間的結構體,然後 fork 並監控 child 進程。Child 進程在主線程的初始化的過程中,將前面打開的存儲文件整個 mmap 到內存中,此時創建並初始化空閒結構體,掛到存儲管理結構體,以待分配。Child 進程分配若干線程進行工作,主要包括一些管理線程和很多 worker 線程。
接着,開始真正的工作,varnish 的某個負責接收新 HTTP 連接線程開始等待用戶,如果有新的 HTTP 連接過來,它總負責接收,然後喚醒某個等待中的線程,並把具體的處理過程交給它。Worker 線程讀入 HTTP 請求的 URI計算出響應的hash值,查找已有的 object,如果命中則直接返回並回複用戶。如果沒有命中,則需要將所請求的內容,從後端服務器中取過來,存到緩存中,然後再回復。
分配緩存的過程是這樣的:它根據所讀到 object 的大小,創建相應大小的緩存文件。爲了讀寫方便,程序會把每個 object 的大小變爲最接近其大小的內存頁面倍數。然後從現有的空閒存儲結構體中查找,找到最合適的大小的空閒存儲塊,分配給它。如果空閒塊沒有用完,就把多餘的內存另外組成一個空閒存儲塊,掛到管理結構體上,這樣做可以減少磁盤碎片。如果緩存已滿,就根據 LRU(最近做少使用原則) 機制,把最舊的 object 釋放掉。
釋放緩存的過程是這樣的:有一個超時線程,檢測緩存中所有 object 的生存期,如果超初設定的 TTL(Time To Live)沒有被訪問,就刪除之,並且釋放相應的結構體及存儲內存。注意釋放時會檢查該存儲內存塊前面或後面的空閒內存塊,如果前面或後面的空閒內存和該釋放內存是連續的,就將它們合併成更大一塊內存。
整個文件緩存的管理,沒有考慮文件與內存的關係,實際上是將所有的 object 都考慮是在內存中,如果系統內存不足,系統會自動將其換到 swap 空間,而不需要 varnish 程序去控制。
四:VCL的內置公共變量
1)當請求到達時,可以使用的公共變量
2)對客戶端相應時可使用公共變量
3)後端主機獲取內容時可使用公共變量
五:varnish試驗
1)試驗拓撲
2)查看安裝的配置文件
[root@varnish ~]# rpm -ql varnish /etc/logrotate.d/varnish /etc/rc.d/init.d/varnish #啓動腳本 /etc/rc.d/init.d/varnishlog /etc/rc.d/init.d/varnishncsa /etc/sysconfig/varnish #啓動腳本的配置文件 /etc/varnish #全局配置文件 /etc/varnish/default.vcl #默認VCL /usr/bin/varnish_reload_vcl #varnish管理工具 /usr/bin/varnishadm /usr/bin/varnishhist /usr/bin/varnishlog /usr/bin/varnishncsa /usr/bin/varnishreplay /usr/bin/varnishsizes /usr/bin/varnishstat /usr/bin/varnishtest /usr/bin/varnishtop /usr/lib64/varnish /usr/lib64/varnish/libvarnish.so /usr/lib64/varnish/libvarnishcompat.so /usr/lib64/varnish/libvcl.so /usr/lib64/varnish/libvgz.so /usr/lib64/varnish/vmods /usr/lib64/varnish/vmods/libvmod_std.so /usr/sbin/varnishd /usr/share/doc/varnish-3.0.4 /usr/share/doc/varnish-3.0.4/ChangeLog /usr/share/doc/varnish-3.0.4/LICENSE /usr/share/doc/varnish-3.0.4/README /usr/share/doc/varnish-3.0.4/README.redhat /usr/share/doc/varnish-3.0.4/examples /usr/share/doc/varnish-3.0.4/examples/default.vcl /usr/share/doc/varnish-3.0.4/examples/zope-plone.vcl /usr/share/man/man1/varnishadm.1.gz #man配置文件 /usr/share/man/man1/varnishd.1.gz /usr/share/man/man1/varnishhist.1.gz /usr/share/man/man1/varnishlog.1.gz /usr/share/man/man1/varnishncsa.1.gz /usr/share/man/man1/varnishreplay.1.gz /usr/share/man/man1/varnishsizes.1.gz /usr/share/man/man1/varnishstat.1.gz /usr/share/man/man1/varnishtest.1.gz /usr/share/man/man1/varnishtop.1.gz /usr/share/man/man3/vmod_std.3.gz /usr/share/man/man7/varnish-cli.7.gz /usr/share/man/man7/varnish-counters.7.gz /usr/share/man/man7/vcl.7.gz /var/lib/varnish /var/log/varnish #日誌文件
3)修改啓動腳本配置文件
[root@varnish sysconfig]# vim /etc/sysconfig/varnish VARNISH_LISTEN_PORT=80 #這裏設置的監聽端口設置爲80 VARNISH_STORAGE="malloc,64M" #我們這裏設置的是64M,因爲我們這裏是測試環境,在生產環境中可以根據實際需求設置很大
4)啓動varnish
[root@varnish ~]# service varnish start Starting Varnish Cache: [確定]
5)配置後端http服務器
[root@web1 ~]# yum install -y httpd [root@web1 ~]# cat /var/www/html/index.html <h1>varnish server node1</h1> [root@web1 ~]# service httpd start 正在啓動 httpd:
6)真假vcl配置文件
[root@varnish ~]# cd /etc/varnish/ [root@varnish varnish]# cp default.vcl test.vcl [root@varnish varnish]# vim test.vcl backend webserver { .host = "172.16.16.1"; .port = "80"; } sub vcl_recv { set req.backend = webserver; }
7)加載vcl配置文件
[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 200 ----------------------------- Varnish Cache CLI 1.0 ----------------------------- Linux,2.6.32-358.el6.x86_64,x86_64,-smalloc,-smalloc,-hcritbit varnish-3.0.4 revision 9f83e8f Type 'help' for command list. Type 'quit' to close CLI session. varnish> vcl.load test test.vcl #編譯 200 VCL compiled. varnish> vcl.list 200 active 0 boot available 0 test varnish> vcl.use test 200
OK,進行測試一下
如何修改配置文件查看我們的緩存是否命中
1)修改配置文件
[root@varnish varnish]# vim test.vcl backend default { .host = "172.16.16.1"; .port = "80"; } sub vcl_recv { set req.backend = webserver; } #修改vcl_deliver增一個響應頭部 sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "Hit from"+" "+server.ip; } else { set resp.http.X-Cache = "Miss via"+" "+server.ip; } }
第一次加載時緩存X-Cache爲Miss(沒有被命中).
第二次刷新加載時命中緩存此處的X-Cache爲HIT.
如何設置讓某個條件不被命中
1)修改配置文件
[root@varnish ~]# vim /etc/varnish/test.vcl backend webserver { .host = "172.16.16.1"; .port = "80"; } #設置條件讓請求test.html文件時不緩存 sub vcl_recv { if (req.url ~ "^/test.html$") { return(pass); } set req.backend = webserver; } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "Hit from"+" "+server.ip; } else { set resp.http.X-Cache = "Miss via"+" "+server.ip; } } [root@web1 ~]# vim /var/www/html/test.html <h1>mandela</h1>
2)重新加載配置文件
varnish> vcl.load test2 test.vcl 200 VCL compiled. varnish> vcl.use test2 200
不管刷新多少次始終是不會對此網頁信息進行緩存.
如何根據響應內容作出判斷
修改配置文件
[root@varnish ~]# vim /etc/varnish/test.vcl backend webserver { .host = "172.16.16.1"; .port = "80"; } sub vcl_recv { if (req.url ~ "^/test.html$") { return(pass); } set req.backend = webserver; } sub vcl_fetch { if (req.request == "GET" && req.url ~ "\.(html|css|js|jpg|jpeg|png|gif)$") { set beresp.ttl = 3600s; } } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "Hit from"+" "+server.ip; } else { set resp.http.X-Cache = "Miss via"+" "+server.ip; } }
重新加載文件
varnish> vcl.load test3 test.vcl 200 VCL compiled. varnish> vcl.use test3 200
varnish如何實現負載均衡及檢查後端主機狀態
修改配置文件
[root@varnish ~]# vim /etc/varnish/test.vcl backend webserver1 { .host = "172.16.16.1"; .port = "80"; .probe = { .url = "/index.html"; .interval = 1s; .window = 3; .threshold = 1; } } backend webserver2 { .host = "172.16.16.4"; .port = "80"; .probe = { .url = "/index.html"; .interval = 1s; .window = 3; .threshold = 1; } } director webserver random { { .backend = webserver1; .weight = 3; } { .backend = webserver2; .weight = 1; } } sub vcl_recv { set req.backend = webserver; } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "Hit from"+" "+server.ip; } else { set resp.http.X-Cache = "Miss via"+" "+server.ip; } }
重新裝載
varnish> vcl.load test4 test.vcl 200 VCL compiled. varnish> vcl.use test4 200
這樣後端定義了兩個主機16.1和16.2.且實現了輪訓調度加緩存機制加後段的安全狀態檢測,後端的安全狀態檢測是每一秒檢測一次,檢測三次不在線就自動下線.判斷在線次數只需要判斷一次.
varnish> backend.list 200 Backend name Refs Admin Probe default(127.0.0.1,,80) 1 probe Healthy (no probe) webserver(172.16.16.1,,80) 4 probe Healthy (no probe) webserver1(172.16.16.1,,80) 3 probe Healthy 3/3 webserver2(172.16.16.4,,80) 3 probe Healthy 3/3
定義的後端主機分別是16.1和16.4
每隔一秒鐘就檢測一下後端主機是否在線.200狀態碼說明主機在線.
OK 我們的varnish配置基本完成.希望大家有些收穫.