1) Varnish工作流程
Varnish是一款高性能的開源HTTP加速器
Varnish與一般服務器軟件類似,分爲master(management)進程和child(worker,主要做cache的工作)進程。master進程讀入命令,進行一些初始化,然後fork並監控child進程。child進程分配若干線程進行工作,主要包括一些管理線程和很多woker線程。
針對文件緩存部分,master讀入存儲配置(-sfile[,path[,size[,granularity]]]),調用合適的存儲類型,然後創建/讀入相應大小的緩存大文件。接着,master初始化管理該存儲空間的結構體。這些變量都是全局變量,在fork以後會被child進程所繼承(包括文件描述符)。
在child進程主線程初始化過程中,將前面打開的存儲大文件整個mmap到內存中(如果超出系統的虛擬內存,mmap失敗,進程會減少原來的配置mmap大小,然後繼續mmap),此時創建並初始化空閒存儲結構體,掛到存儲管理結構體,以待分配。
接着,真正的工作開始,Varnish的某個負責接受新HTTP連接的線程開始等待用戶,如果有新的HTTP連接過來,它總負責接收,然後叫醒某個等待中的線程,並把具體的處理過程交給它。Worker線程讀入HTTP請求的URI,查找已有的object,如果命中則直接返回並回複用戶。如果沒有命中,則需要將所請求的內容,從後端服務器中取過來,存到緩存中,然後再回復。
分配緩存的過程是這樣的:它根據所讀到object的大小,創建相應大小的緩存文件。爲了讀寫方便,程序會把每個object的大小變爲最接近其大小的內存頁面倍數。然後從現有的空閒存儲結構體中查找,找到最合適的大小的空閒存儲塊,分配給它。如果空閒塊沒有用完,就把多餘的內存另外組成一個空閒存儲塊,掛到管理結構體上。如果緩存已滿,就根據LRU機制,把最舊的object釋放掉。
釋放緩存的過程是這樣的:有一個超時線程,檢測緩存中所有object的生存期,如果超初設定的TTL(TimeToLive)沒有被訪問,就刪除之,並且釋放相應的結構體及存儲內存。注意釋放時會檢查該存儲內存塊前面或後面的空閒內存塊,如果前面或後面的空閒內存和該釋放內存是連續的,就將它們合併成更大一塊內存。
整個文件緩存的管理,沒有考慮文件與內存的關係,實際上是將所有的object都考慮是在內存中,如果系統內存不足,系統會自動將其換到swap空間,而不需要varnish程序去控制。
2) varnish的安裝和啓動配置
[root@lab1 varnish]# ls ~/varnish/ 3.0.5 varnish-libs-3.0.4-1.el6.x86_64.rpm varnish-3.0.4-1.el6.x86_64.rpm varnish-libs-devel-3.0.4-1.el6.x86_64.rpm varnish-docs-3.0.4-1.el6.x86_64.rpm [root@lab1 varnish]# yum install varnish*.rpm #編輯/etc/sysconfig/varnish,將監聽端口改爲80 VARNISH_LISTEN_PORT=80 #編輯/etc/varnish/default.vcl,將監聽服務器妨礙爲172.16.21.102:80 backend default { .host = "172.16.21.102"; .port = "80"; } #啓動服務 service varnish start
#此時我們已經可以訪問arnish服務器172.16.21.101了
現在我們可以使用varnishadmin來配置varnish了
[root@node0 varnish]# varnishadm
3) 配置varnish添加X-Cache頭部以判斷緩存是否命中
#拷貝default.vcl到test1.vcl co default.vcl test1.vcl #編輯tes1.vcl在sub vcl_deliver段中添加 sub vcl_deliver { if(obj.hits>0){ #如果命中次數大於0 set resp.http.X-Cache = "HIT"; }else{ set resp.http.X-Cache = "MISS"; } return (deliver); } #加載並啓用test1.vcl varnish> vcl.load test ./test1.vcl 200 VCL compiled. varnish> vcl.use test 200
訪問測試,沒有命中
再次訪問,可以看到已經命中
4) 配置指定頁面不可以被緩存
再次編輯test1.vcl.添加如下內容
sub vcl_recv { if (req.url ~ "miss.html"){ #如果url被miss.html匹配,不要緩存,直接進入pass return(pass); } return (lookup); } #加載配置 varnish> vcl.load test2 ./test1.vcl 200 VCL compiled. varnish> vcl.use test2 200 #在102添加miss.html文件 [root@lab2 html]# echo "<h1>Can't be Cached</h1>" > miss.html
訪問miss.html,可見無論如何刷新都不會命中緩存
5) 設置圖片緩存時間,取消圖片cookie設置
sub vcl_fetch { if (req.url ~ "\.(jpg|jpeg|gif|png)"){ #如果文件以指定格式結尾,使其緩存兩個小時 set beresp.ttl=7200s; unset beresp.http.Set-Cookie; } }
6) 設置緩存修剪及修剪控制
#修改配置文件 [root@lab1 varnish]# cat /etc/varnish/test1.vcl |grep -v "^#" backend default { .host = "172.16.21.102"; .port = "80"; } acl purgers { #訪問控制列表 "127.0.0.1"; "172.16.21.0"/24; } sub vcl_recv { if (req.request == "PURGE"){ #如果請求方法爲PURGE並且 if(! client.ip ~ purgers) { #客戶端ip不在列表中 error 406 "Method not allowed IN the address"; #生成錯誤報文並退出 } if (req.url ~ "miss.html"){ return(pass); } } return (lookup); } sub vcl_pass { if(req.request == "PURGE") { error 502 " Purge on a passwd object"; } return (pass); } sub vcl_hit { if(req.request == "PURGE") { purge; error 201 " Purged"; } return (deliver); } sub vcl_miss { if(req.request == "PURGE") { purge; error 405 " Not Found in Cache"; } return (fetch); } sub vcl_fetch { if (req.url ~ "\.(jpg|jpeg|gif|png)"){ set beresp.ttl=7200s; unset beresp.http.Set-Cookie; } } sub vcl_deliver { if(obj.hits>0){ set resp.http.X-Cache = "HIT"; }else{ set resp.http.X-Cache = "MISS"; } return (deliver); } #修剪測試 [root@lab1 varnish]# curl -X PURGE 172.16.21.101 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>201 Purged</title> </head> <body> <h1>Error 201 Purged</h1> Purged <h3>Guru Meditation:</h3> XID: 587750580 <hr> Varnish cache server </body> </html> [root@lab1 varnish]# curl -X PURGE 172.16.21.101/miss.html <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>502 Purge on a passwd object</title> </head> <body> <h1>Error 502 Purge on a passwd object</h1> Purge on a passwd object <h3>Guru Meditation:</h3> XID: 587750582 <hr> Varnish cache server </body> </html>
7) 設置varnish使用多臺後端主機
#編輯配置文件 [root@lab1 varnish]# cat /etc/varnish/test1.vcl |grep -v "^#" backend web1 { .host = "172.16.21.102"; .port = "80"; } backend web2 { .host = "172.16.21.103"; .port = "80"; } director webservers random { .retries = 5; { .backend = web1; .weight = 2 ; } { .backend = web2; .weight = 3 ; } } ... sub vcl_recv { set req.backend = webservers; } return (lookup); } #重新加載並使用 varnish> vcl.load test9 ./test1.vcl 200 VCL compiled. varnish> vcl.use test9 200
#訪問測試
#清除緩存後訪問,
curl -X PURGE 172.16.21.101/