一、Varish的簡介
Varnish是一款高性能的開源HTTP加速器,挪威最大的線上報紙 Verdens Gang 使用3台Varnish代替了原來的12台Squid,性能比以前更好。
在目前主流的Web架構中,Cache擔任着越來越重要的作用。常見的基于浏覽器的C/S架構,Web Cache更是節約伺服器資源的關鍵。而最近幾年由FreeBSD創始人之一Kamp開發的varnish更是一個不可多得的Web Cache Server。嚴格意義上說,Varnish是一個高性能的反向代理軟體,隻不過與其出色的緩存功能相比,企業更願意使用其搭建緩存伺服器。同時,由于其工作在Web Server的前端,有一部分企業已經在生産環境中使用其作為舊版本的squid的替代方案,以在相同的伺服器成本下提供更好的緩存效果,Varnish更是作為CDN緩存伺服器的可選服務之一。
二、關于Varnish
1、varnish系統架構
varnish主要運作兩個程序:Management程序和Child程序(也叫Cache程序)。
Management程序
主要實作應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個指令行接口等。Management程序會每隔幾秒鐘探測一下Child程序以判斷其是否正常運作,如果在指定的時長内未得到Child程序的回應,Management将會重新開機此Child程序。
Child程序包含多種類型的線程,常見的如:
Acceptor線程:接收新的連接配接請求并響應;
Worker線程:child程序會為每個會話啟動一個worker線程,是以,在高并發的場景中可能會出現數百個worker線程甚至更多;
Expiry線程:從緩存中清理過期内容;
Varnish依賴“工作區(workspace)”以降低線程在申請或修改記憶體時出現競争的可能性。在varnish内部有多種不同的工作區,其中最關鍵的當屬用于管理會話資料的session工作區。
2、varnish日志
為了與系統的其它部分進行互動,Child程序使用了可以通過檔案系統接口進行通路的共享記憶體日志(shared memory log),是以,如果某線程需要記錄資訊,其僅需要持有一個鎖,而後向共享記憶體中的某記憶體區域寫入資料,再釋放持有的鎖即可。而為了減少競争,每個worker線程都使用了日志資料緩存。
共享記憶體日志大小一般為90M,其分為兩部分,前一部分為計數器,後半部分為用戶端請求的資料。varnish提供了多個不同的工具如varnishlog、varnishncsa或varnishstat等來分析共享記憶體日志中的資訊并能夠以指定的方式進行顯示。
3、VCL
Varnish Configuration Language (VCL)是varnish配置緩存政策的工具,它是一種基于“域”(domain specific)的簡單程式設計語言,它支援有限的算術運算和邏輯運算操作、允許使用正規表達式進行字元串比對、允許使用者使用set自定義變量、支援if判斷語句,也有内置的函數和變量等。使用VCL編寫的緩存政策通常儲存至.vcl檔案中,其需要編譯成二進制的格式後才能由varnish調用。事實上,整個緩存政策就是由幾個特定的子例程如vcl_recv、vcl_fetch等組成,它們分别在不同的位置(或時間)執行,如果沒有事先為某個位置自定義子例程,varnish将會執行預設的定義。
VCL政策在啟用前,會由management程序将其轉換為C代碼,而後再由gcc編譯器将C代碼編譯成二進制程式。編譯完成後,management負責将其連接配接至varnish執行個體,即child程序。正是由于編譯工作在child程序之外完成,它避免了裝載錯誤格式VCL的風險。是以,varnish修改配置的開銷非常小,其可以同時保有幾份尚在引用的舊版本配置,也能夠讓新的配置即刻生效。編譯後的舊版本配置通常在varnish重新開機時才會被丢棄,如果需要手動清理,則可以使用varnishadm的vcl.discard指令完成。
4、varnish的後端存儲
varnish支援多種不同類型的後端存儲,這可以在varnishd啟動時使用-s選項指定。後端存儲的類型包括:
(1)file:使用特定的檔案存儲全部的緩存資料,并通過作業系統的mmap()系統調用将整個緩存檔案映射至記憶體區域(如果條件允許);
(2)malloc:使用malloc()庫調用在varnish啟動時向作業系統申請指定大小的記憶體空間以存儲緩存對象;
(3)persistent(experimental):與file的功能相同,但可以持久存儲資料(即重新開機varnish資料時不會被清除);仍處于測試期;
varnish無法追蹤某緩存對象是否存入了緩存檔案,進而也就無從得知磁盤上的緩存檔案是否可用,是以,file存儲方法在varnish停止或重新開機時會清除資料。而persistent方法的出現對此有了一個彌補,但persistent仍處于測試階段,例如目前尚無法有效處理要緩存對象總體大小超出緩存空間的情況,是以,其僅适用于有着巨大緩存空間的場景。
選擇使用合适的存儲方式有助于提升系統性,從經驗的角度來看,建議在記憶體空間足以存儲所有的緩存對象時使用malloc的方法,反之,file存儲将有着更好的性能的表現。然而,需要注意的是,varnishd實際上使用的空間比使用-s選項指定的緩存空間更大,一般說來,其需要為每個緩存對象多使用差不多1K左右的存儲空間,這意味着,對于100萬個緩存對象的場景來說,其使用的緩存空間将超出指定大小1G左右。另外,為了儲存資料結構等,varnish自身也會占去不小的記憶體空間。
為varnishd指定使用的緩存類型時,-s選項可接受的參數格式如下:
malloc[,size] 或
file[,path[,size[,granularity]]] 或
persistent,path,size {experimental}
file中的granularity用于設定緩存空間配置設定機關,預設機關是位元組,所有其它的大小都會被圓整。
三、安裝varnish
官方最新版本:Varnish Cache 4.0.1
Varnish學習需要注意的要素:
1、Varnish要安裝在64的系統上
2、Varnish使用記憶體做緩存大小為2G,基本就可以了;無論是memcache還是varnish基于記憶體做緩存都不宜太大,太大沒有好處,它有一個臨界值,如果緩存設定太小,那麼資料緩存會頻繁被清除掉;如果緩存設定太大的,那麼緩存會永久存放,有些過期的也不會被清除掉,并且資料過多的查找起來也慢。建議Varnish緩存設定大小為1G-2G之間就可以了。
1、yum安裝varnish
1
2
<code>[root@Varnish ~]</code><code># rpm --nosignature -i https://repo.varnish-cache.org/redhat/varnish-3.0.el6.rpm</code>
<code>[root@Varnish ~]</code><code># yum -y install varnish</code>
2、Varnish的配置檔案說明
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<code>[root@Varnish ~]</code><code># grep -v "^#" /etc/sysconfig/varnish |sed '/^$/d'</code>
<code>NFILES=131072 </code><code># 最大打開檔案數65536*2{ulimit -n}</code>
<code>MEMLOCK=82000 </code><code># 鎖定使用多大的共享記憶體來儲存日志資訊,預設為82M</code>
<code>NPROCS=</code><code>"unlimited"</code> <code># 最大的線程數,預設無限制</code>
<code># DAEMON_COREFILE_LIMIT="unlimited" # 程序核心轉儲所使用的記憶體空間,unlimited表示無上限</code>
<code>RELOAD_VCL=1 </code><code># 設定為1可以使用restart自動加載vcl配置檔案</code>
<code>VARNISH_VCL_CONF=</code><code>/etc/varnish/default</code><code>.vcl </code><code># 定義vcl配置檔案</code>
<code>VARNISH_LISTEN_PORT=6081 </code><code># 定義varnish服務監聽端口</code>
<code>VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 </code><code># 定義允許進行程序管理位址</code>
<code>VARNISH_ADMIN_LISTEN_PORT=6082 </code><code># 定義管理程序監聽端口</code>
<code>VARNISH_SECRET_FILE=</code><code>/etc/varnish/secret</code> <code># 定義秘鑰和簽名認證檔案</code>
<code>VARNISH_MIN_THREADS=50 </code><code># 定義varnish啟動時最小線程數</code>
<code>VARNISH_MAX_THREADS=1000 </code><code># 定義varnish啟動時最大線程數</code>
<code>VARNISH_THREAD_TIMEOUT=120 </code><code># 定義varnish線程響應逾時時間</code>
<code>VARNISH_STORAGE_FILE=</code><code>/var/lib/varnish/varnish_storage</code><code>.bin </code><code># 定義varnish的緩存檔案</code>
<code>VARNISH_STORAGE_SIZE=1G </code><code># 定義緩存使用檔案大小,機關:k/M/G/T</code>
<code>VARNISH_STORAGE=</code><code>"file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"</code> <code># 使用檔案緩存</code>
<code>#VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}" # 使用記憶體緩存;malloc</code>
<code>VARNISH_TTL=120 </code><code># 如果後端伺服器沒有設定資料緩存多長時間,則預設為120秒</code>
<code>DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \ </code><code># 變量調用</code>
<code> </code><code>-f ${VARNISH_VCL_CONF} \</code>
<code> </code><code>-T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \</code>
<code> </code><code>-t ${VARNISH_TTL} \</code>
<code> </code><code>-w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \</code>
<code> </code><code>-u varnish -g varnish \</code>
<code> </code><code>-S ${VARNISH_SECRET_FILE} \ </code><code>#前端和後端在通信的過程中實作加密和簽名的迷藥檔案,防止别人篡改資料的。</code>
<code> </code><code>-s ${VARNISH_STORAGE}"</code>
3、Varnish的VCL配置說明
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<code>[root@Varnish ~]</code><code># cat /etc/varnish/default.vcl </code>
<code>#定義後端預設的伺服器</code>
<code>backend default {</code>
<code> </code><code>.host = </code><code>"127.0.0.1"</code><code>; </code>
<code> </code><code>.port = </code><code>"80"</code><code>; </code>
<code>} </code>
<code>#定義一個vcl_recv函數 </code>
<code>sub vcl_recv {</code>
<code>#req.restarts可以解釋為如果用戶端第一次開始請求時,</code>
<code>#如果請求的http中含有X-Forwarded-For資訊,不管如何都在該資訊後面附加用戶端的ip位址資訊;</code>
<code>#若不含有X-Forwarded-For資訊,則直接附加client.ip位址資訊。</code>
<code>#X-Forwarded-For通常表示代理伺服器的位址</code>
<code>#為什麼要補充client.ip呢?因為varnish做了反向代理,為了使後端伺服器記錄用戶端的ip位址而非varnish的位址</code>
<code> </code><code>if</code> <code>(req.restarts == 0) {</code>
<code> </code><code>if</code> <code>(req.http.x-forwarded-</code><code>for</code><code>) {</code>
<code> </code><code>set</code> <code>req.http.X-Forwarded-For =</code>
<code> </code><code>req.http.X-Forwarded-For + </code><code>", "</code> <code>+ client.ip;</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>set</code> <code>req.http.X-Forwarded-For = client.ip;</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code>#定義http請求的方法;如果用戶端請求的http的方法不是GET/HEAD/PUT/POST/TRAGE/OPTIONS/DELETE,</code>
<code>#那麼我們的varnish就不會去把請求傳遞給varnish的vcl_hash,直接交給pipe,表示varnish無法了解或者認為是非法的請求。</code>
<code> </code><code>if</code> <code>(req.request != </code><code>"GET"</code> <code>&&</code>
<code> </code><code>req.request != </code><code>"HEAD"</code> <code>&&</code>
<code> </code><code>req.request != </code><code>"PUT"</code> <code>&&</code>
<code> </code><code>req.request != </code><code>"POST"</code> <code>&&</code>
<code> </code><code>req.request != </code><code>"TRACE"</code> <code>&&</code>
<code> </code><code>req.request != </code><code>"OPTIONS"</code> <code>&&</code>
<code> </code><code>req.request != </code><code>"DELETE"</code><code>) {</code>
<code> </code><code>/* Non-RFC2616 or CONNECT </code><code>which</code> <code>is weird. */</code>
<code> </code><code>return</code> <code>(pipe);</code>
<code>#如果請求的方法不是GET,也不是HEAD,那麼有可能就是PUT,POST,這些都是上傳資料的,</code>
<code>#對于上傳的資料,我們沒有必要緩存,直接跟後端伺服器互動。</code>
<code> </code><code>if</code> <code>(req.request != </code><code>"GET"</code> <code>&& req.request != </code><code>"HEAD"</code><code>) {</code>
<code> </code><code>/* We only deal with GET and HEAD by default */</code>
<code> </code><code>return</code> <code>(pass); </code><code>#不查找緩存,直接從後端伺服器擷取資料</code>
<code>#如果請求的内容中包括Authorization授權的,包括Cookie認證的,這些都是使用者的敏感資料,一定不能緩存的。</code>
<code> </code><code>if</code> <code>(req.http.Authorization || req.http.Cookie) {</code>
<code> </code><code>/* Not cacheable by default */</code>
<code> </code><code>return</code> <code>(pass);</code>
<code> </code><code>return</code> <code>(lookup); </code><code>#lookup表示從緩存中查找</code>
<code>} </code>
<code> </code>
<code>#從後端伺服器fetch資料</code>
<code>sub vcl_pass {</code>
<code> </code><code>return</code> <code>(pass);</code>
<code>}</code>
<code>sub vcl_hash { </code><code>#定義vcl_hash函數</code>
<code> </code><code>hash_data(req.url); </code><code>#預設是根據使用者請求的url做hash</code>
<code> </code><code>if</code> <code>(req.http.host) { </code><code>#如果使用者的請求http的首部中有host,那麼就對此做hash</code>
<code> </code><code>hash_data(req.http.host);</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>hash_data(server.ip); </code><code>#否則根據伺服器端的位址做hash</code>
<code> </code><code>return</code> <code>(</code><code>hash</code><code>); </code><code>#最終傳回hash資料</code>
<code>#如果命中的則直接從本地緩存中傳回資料給使用者</code>
<code>sub vcl_hit {</code>
<code> </code><code>return</code> <code>(deliver);</code>
<code>#如果沒有命中,則從後端伺服器取資料</code>
<code>sub vcl_miss {</code>
<code> </code><code>return</code> <code>(fetch);</code>
<code>#如果沒有命中,那麼從後端伺服器取資料應該怎樣取呢?</code>
<code>#在響應用戶端之前,如果ttl頭部值小于等于0秒,表示緩存已經過期了,</code>
<code>#并且其中包含有"Set-Cookie","Vary"這些字段,那麼就直接設定這些過期的緩存資訊的緩存期限為120秒</code>
<code>#如果其中沒有這些字段的話就直接緩存下來了。</code>
<code>sub vcl_fetch {</code>
<code> </code><code>if</code> <code>(beresp.ttl <= 0s || </code>
<code> </code><code>beresp.http.Set-Cookie || </code>
<code> </code><code>beresp.http.Vary == </code><code>"*"</code><code>) {</code>
<code> </code><code>/*</code>
<code> </code><code>* Mark as </code><code>"Hit-For-Pass"</code> <code>for</code> <code>the next 2 minutes</code>
<code> </code><code>*/</code>
<code> </code><code>set</code> <code>beresp.ttl = 120 s;</code>
<code> </code><code>return</code> <code>(hit_for_pass);</code>
<code>sub vcl_deliver {</code>
<code>#用戶端請求某個頁面,如果伺服器上不存在這個頁面,就請求錯誤</code>
<code>#對于後端伺服器沒有這個檔案的,直接交由varnish響應一個錯誤資訊</code>
<code>sub vcl_error {</code>
<code> </code><code>set</code> <code>obj.http.Content-Type = </code><code>"text/html; charset=utf-8"</code><code>;</code>
<code> </code><code>set</code> <code>obj.http.Retry-After = </code><code>"5"</code><code>;</code>
<code> </code><code>synthetic {"</code>
<code><?xml version=</code><code>"1.0"</code> <code>encoding=</code><code>"utf-8"</code><code>?></code>
<code><!DOCTYPE html PUBLIC </code><code>"-//W3C//DTD XHTML 1.0 Strict//EN"</code>
<code> </code><code>"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"</code><code>></code>
<code><html></code>
<code> </code><code><</code><code>head</code><code>></code>
<code> </code><code><title></code><code>"} + obj.status + "</code> <code>" + obj.response + {"</code><code><</code><code>/title</code><code>></code>
<code> </code><code><</code><code>/head</code><code>></code>
<code> </code><code><body></code>
<code> </code><code><h1>Error </code><code>"} + obj.status + "</code> <code>" + obj.response + {"</code><code><</code><code>/h1</code><code>></code>
<code> </code><code><p></code><code>"} + obj.response + {"</code><code><</code><code>/p</code><code>></code>
<code> </code><code><h3>Guru Meditation:<</code><code>/h3</code><code>></code>
<code> </code><code><p>XID: </code><code>"} + req.xid + {"</code><code><</code><code>/p</code><code>></code>
<code> </code><code><hr></code>
<code> </code><code><p>Varnish cache server<</code><code>/p</code><code>></code>
<code> </code><code><</code><code>/body</code><code>></code>
<code><</code><code>/html</code><code>></code>
<code>"};</code>
<code>sub vcl_init {</code>
<code> </code><code>return</code> <code>(ok);</code>
<code>sub vcl_fini {</code>
四、Varnish狀态引擎以及工作原理說明
<a href="http://s3.51cto.com/wyfs02/M02/53/7B/wKioL1Rot_TCI59vAAH002Hq3FI410.jpg" target="_blank"></a>
<code>vcl_recv:用于接收到使用者的請求</code>
<code>在vcl_hit引擎中可以調用</code><code>return</code><code>(pipe)指令和調用</code><code>return</code><code>(lookup)指令和調用</code><code>return</code><code>(pass)指令。</code>
<code>如果不檢查緩存;</code>
<code> </code><code>調用的是</code><code>return</code><code>(pipe)指令,然後由vcl_pipe引擎直接交給後端伺服器進行處理</code>
<code>如果是檢查緩存;</code>
<code> </code><code>調用</code><code>return</code><code>(lookup)指令,檢查緩存,看緩存是否命中,需自行定義如何</code>
<code>檢查緩存</code>
<code> </code><code>調用</code><code>return</code><code>(pass)指令,則将請求送給vcl_pass進行處理</code>
<code>vcl_pipe:用于把使用者的請求接進來,然後建立一個管道直接交給後端伺服器</code>
<code> </code><code>在vcl_pipe引擎中可以調用</code><code>return</code><code>(pipe)指令</code>
<code> </code><code>調用</code><code>return</code><code>(pipe)指令則建立一個與後端伺服器的管道</code>
<code>vcl_hash:用于自行定義其它緩存的機制</code>
<code> </code><code>在vcl_hash引擎中可以調用</code><code>return</code><code>(</code><code>hash</code><code>)指令</code>
<code> </code><code>調用</code><code>return</code><code>(</code><code>hash</code><code>)指令,則通過</code><code>hash</code><code>鍵值對進行判斷,是否命中</code>
<code>vcl_hit:用于表示緩存命中</code>
<code>在vcl_hit引擎中可以調用</code><code>return</code><code>(pass)指令和調用</code><code>return</code><code>(delive)指令</code>
<code> </code><code>如果是調用</code><code>return</code><code>(pass)指令,則将請求送給vcl_pass進行處理</code>
<code> </code><code>{此情況發生在當自定義的緩存為1個小時,但未滿一個小時,所設定的緩存已經發生變化則需要用vcl_pass}</code>
<code> </code><code>如果是調用</code><code>return</code><code>(delive)指令,則從緩存中直接取出後由vcl_deliver傳回給使用者</code>
<code>vcl_miss:用于表示緩存未命中</code>
<code>在vcl_miss引擎中可以調用</code><code>return</code><code>(pass)指令和調用</code><code>return</code><code>(fetch)指令</code>
<code> </code><code>如果是調用</code><code>return</code><code>(fetch)指令,則将請求送給vcl_fetch進行處理</code>
<code>vcl_pass:用于給命中引擎和未命中引擎提供處理機制</code>
<code>在vcl_pass引擎中可以調用</code><code>return</code><code>(fetch)指令</code>
<code> </code><code>調用</code><code>return</code><code>(fetch)指令,則将請求送給vcl_fetch進行處理</code>
<code>vcl_fetch:用于到後端伺服器去取資料</code>
<code>在vcl_fetch引擎中可以調用</code><code>return</code><code>(delive)指令和調用</code><code>return</code><code>(pass)指令</code>
<code> </code><code>如果是調用</code><code>return</code><code>(delive)指令,則把後端取的資料儲存在緩存中</code>
<code> </code><code>如果是調用</code><code>return</code><code>(pass)指令,則不把後端取的資料儲存在緩存中</code>
<code>vcl_deliver:用于從緩存中取資料傳回給使用者</code>
<code>vcl_error:用于由varnish直接建構錯誤響應封包</code>
<a href="http://s3.51cto.com/wyfs02/M00/53/7B/wKioL1RouYDg7sj-AAZBXldc0_0976.jpg" target="_blank"></a>
************************
<code>vcl_recv:使用者請求到達varnish之後,varnish就要vcl函數做一些驗證和處理操作。</code>
<code> </code><code>pipe:管道 送給其它的程序或其它的機制來處理,一般用的比較少。</code>
<code> </code><code>pass:不查找本地緩存,直接從後端伺服器擷取資料。</code>
<code> </code><code>lookup:查找,從本地緩存中查找,</code>
<code> </code><code>vcl_hash:定義對使用者查找的連結做vcl運算并比較的,是以我們用使用者請求的url連結根據自已定義的vcl方式做</code><code>hash</code><code>計算以後,就會得到</code><code>hash</code><code>碼;</code>
<code> </code><code>為了使緩存中的資料查找效率高,這些緩存中的資料都是以鍵值對的方式存儲的,key(url)和value(object)</code>
<code> </code><code>這裡的key是使用者請求的url,value是使用者請求的檔案内容,我們叫緩存對象。</code>
<code> </code><code>如果直接用url來做key,那麼查找起來是十分緩慢的,往往都是把url做</code><code>hash</code><code>編碼,可以指定</code><code>hash</code><code>編碼的算法。得到</code><code>hash</code><code>碼。 </code>
<code> </code><code>Is the object </code><code>in</code> <code>cache?:如果用得到的</code><code>hash</code><code>碼給現存緩存清單中的key做比較,如果有一樣的則就命中緩存了。否則緩存沒有命中。</code>
<code> </code><code>vcl_miss:</code>
<code> </code><code>vcl_pass:</code>
<code> </code><code>{</code>
<code> </code><code>(vcl_pass)pass:如果沒有命中,多一步驗證措施</code>
<code> </code><code>(vcl_pass)fetch:到後端伺服器取資料</code>
<code> </code><code>}</code>
<code> </code><code>vcl_hit:</code>
<code> </code><code>{</code>
<code> </code><code>(vcl_hit)pass:盡管命中的也不在緩存中傳回,而是從後端伺服器取資料,因為這些資料可能是私有的,比如登陸賬戶、密碼,認證加密檔案</code>
<code> </code><code>(vcl_hit)deliver:表示如果命中了并想資料緩存下來或者說把資料做緩存了,在或者說從緩存中取資料了。</code>
<code> </code><code>}</code>
<code> </code><code>deliver:</code>
<code> </code>
<code> </code><code>Fetch object from backend:表示從後端伺服器取資料</code>
<code> </code><code>vcl_fetch</code>
<code> </code><code>Cache(deliver):先緩存在傳回給使用者</code>
<code> </code><code>Dont't cache(pass):不緩存直接傳回給使用者</code>
<code> </code><code>vcl_deliver:</code>
五、Varnish的一些補充指令說明
1、啟動varnish指令
<code># /etc/init.d/varnish start</code>
2、檢視varnish監聽的端口
<code># netstat -tnlp |grep varnish</code>
<code>tcp 0 0 0.0.0.0:6081 0.0.0.0:* LISTEN 1397</code><code>/varnishd</code>
<code>tcp 0 0 127.0.0.1:6082 0.0.0.0:* LISTEN 1396</code><code>/varnishd</code>
<code>tcp 0 0 :::6081 :::* LISTEN 1397</code><code>/varnishd</code>
3、varnishadm的管理工具指令
<code>[root@Varnish ~]</code><code># varnishadm -h</code>
<code>varnishadm: invalid option -- </code><code>'h'</code>
<code>usage: varnishadm [-n ident] [-t timeout] [-S secretfile] -T [address]:port </code><code>command</code> <code>[...]</code>
<code> </code><code>-n is mutually exlusive with -S and -T</code>
<code>[root@Varnish ~]</code><code># varnishadm -T 127.0.0.1:6082 -S /etc/varnish/secret # 登入管理指令行</code>
<code>200 </code>
<code>-----------------------------</code>
<code>Varnish Cache CLI 1.0</code>
<code>Linux,2.6.32-358.el6.x86_64,x86_64,-sfile,-smalloc,-hcritbit</code>
<code>varnish-3.0.6 revision 1899836</code>
<code>Type </code><code>'help'</code> <code>for</code> <code>command</code> <code>list.</code>
<code>Type </code><code>'quit'</code> <code>to close CLI session.</code>
<code>varnish> help </code><code>#檢視幫助指令</code>
<code>help [</code><code>command</code><code>]</code>
<code>ping</code> <code>[timestamp]</code>
<code>auth response</code>
<code>quit</code>
<code>banner</code>
<code>status</code>
<code>start</code>
<code>stop</code>
<code>vcl.load <configname> <filename></code>
<code>vcl.inline <configname> <quoted_VCLstring></code>
<code>vcl.use <configname></code>
<code>vcl.discard <configname></code>
<code>vcl.list</code>
<code>vcl.show <configname></code>
<code>param.show [-l] [<param>]</code>
<code>param.</code><code>set</code> <code><param> <value></code>
<code>panic.show</code>
<code>panic.</code><code>clear</code>
<code>storage.list</code>
<code>backend.list</code>
<code>backend.set_health matcher state</code>
<code>ban.url <regexp></code>
<code>ban <field> <operator> <arg> [&& <field> <oper> <arg>]...</code>
<code>ban.list</code>
<code>varnish> </code><code>ping</code> <code># 測試ping指令</code>
<code>PONG 1416045552 1.0</code>
<code>varnish> vcl.load d1 </code><code>/etc/varnish/default</code><code>.vcl </code><code># 加載編譯新配置, d1是配置名,default.vcl是配置檔案</code>
<code>VCL compiled.</code>
<code>varnish> vcl.list </code><code># 列出所有的配置</code>
<code>active 0 boot</code>
<code>available 0 d1</code>
<code>varnish> vcl.use d1 </code><code># 使用配置,需指定配置名,目前使用的配置以最後一次vcl.use為準</code>
<code>varnish> backend.list </code><code>#檢視配置檔案的配置資訊</code>
<code>Backend name Refs Admin Probe</code>
<code>default(127.0.0.1,,80) 2 probe Healthy (no probe)</code>
<code>varnish> storage.list </code><code>#檢視儲存清單資訊</code>
<code>Storage devices:</code>
<code> </code><code>storage.Transient = malloc</code>
<code> </code><code>storage.s0 = </code><code>file</code>
六、Varnish檢測後端主機的健康狀态
Varnish可以檢測後端主機的健康狀态,在判定後端主機失效時能自動将其從可用後端主機清單中移除,而一旦其重新變得可用還可以自動将其設定為可用。為了避免誤判,Varnish在探測後端主機的健康狀态發生轉變時(比如某次探測時某後端主機突然成為不可用狀态),通常需要連續執行幾次探測均為新狀态才将其标記為轉換後的狀态。
每個後端伺服器目前探測的健康狀态探測方法通過.probe進行設定,其結果可由req.backend.healthy變量擷取,也可通過varnishlog中的Backend_health檢視或varnishadm的debug.health檢視。
backend web1 {
.host = "www.allentuns.com";
.probe = {
.url = "/.healthtest.html";
.interval = 1s;
.window = 5;
.threshold = 2;
}
.probe中的探測指令常用的有:
(1) .url:探測後端主機健康狀态時請求的URL,預設為“/”;
(2) .request: 探測後端主機健康狀态時所請求内容的詳細格式,定義後,它會替換.url指定的探測方式;比如:
.request =
"GET /.healthtest.html HTTP/1.1"
"Host: www.allentuns.com"
"Connection: close";
(3) .window:設定在判定後端主機健康狀态時基于最近多少次的探測進行,預設是8;
(4) .threshold:在.window中指定的次數中,至少有多少次是成功的才判定後端主機正健康運作;預設是3;
(5) .initial:Varnish啟動時對後端主機至少需要多少次的成功探測,預設同.threshold;
(6) .expected_response:期望後端主機響應的狀态碼,預設為200;
(7) .interval:探測請求的發送周期,預設為5秒;
(8) .timeout:每次探測請求的過期時長,預設為2秒;
是以,如上示例中表示每隔1秒對此後端主機www.allentuns.com探測一次,請求的URL為http://www.allentuns.com/.healthtest.html,在最近5次的探測請求中至少有2次是成功的(響應碼為200)就判定此後端主機為正常工作狀态。
如果Varnish在某時刻沒有任何可用的後端主機,它将嘗試使用緩存對象的“寬容副本”(graced copy),當然,此時VCL中的各種規則依然有效。是以,更好的辦法是在VCL規則中判斷req.backend.healthy變量顯示某後端主機不可用時,為此後端主機增大req.grace變量的值以設定适用的寬容期限長度。
七、Varnish的負載均衡和動靜分離配置檔案
在實際生産環境中對後端server進行健康狀态檢查的時候;
靜态的在網頁根目錄建立一個test.html檢測頁面,動态的在網頁根目錄先建立一個test.jsp的檢測頁面
<code># Configure VCL</code>
<code>probe static_chk { </code><code>#靜态網頁的健康狀态檢查</code>
<code> </code><code>.url = </code><code>"/test.html"</code><code>;</code>
<code> </code><code>.interval = 2s;</code>
<code> </code><code>.timeout = 2s;</code>
<code> </code><code>.expected_response = 200;</code>
<code>probe dynamic_chk { </code><code>#動态網頁的健康狀态檢查</code>
<code> </code><code>.url = </code><code>"/test.php"</code><code>;</code>
<code>backend apache01 { </code><code>#靜态請求負載均衡1</code>
<code> </code><code>.host = </code><code>"192.168.0.108"</code><code>;</code>
<code> </code><code>.port = </code><code>"80"</code><code>;</code>
<code> </code><code>.probe = static_chk;</code>
<code>backend apache02 { </code><code>#靜态請求負載均衡2</code>
<code> </code><code>.host = </code><code>"192.168.0.110"</code><code>;</code>
<code>backend nginx01 { </code><code>#動态請求分發位址</code>
<code> </code><code>.host = </code><code>"192.168.0.100"</code><code>;</code>
<code> </code><code>.probe = dynamic_chk;</code>
<code>director myload random { </code><code>#分發器和排程算法</code>
<code> </code><code>.retries = 2;</code>
<code> </code><code>{</code>
<code> </code><code>.backend = apache01;</code>
<code> </code><code>.weight = 1;</code>
<code> </code><code>}</code>
<code> </code><code>.backend = apache02;</code>
<code> </code><code>set</code> <code>req.http.X-Forward-For = client.ip; </code><code>#記錄用戶端的ip位址</code>
<code> </code><code>if</code> <code>(req.url ~ </code><code>"\.(html)$"</code> <code>) {</code>
<code> </code><code>return</code><code>(lookup);</code>
<code> </code><code>if</code> <code>(req.url ~ </code><code>"\.(php)$"</code><code>) { </code><code>#如果請求的是php檔案則将請求發送給nginx代理的伺服器</code>
<code> </code><code>set</code> <code>req.backend = nginx01;</code>
<code> </code><code>}</code><code>else</code><code>{</code>
<code> </code><code>set</code> <code>req.backend = myload; </code><code>#如果請求的是html檔案則将請求發送給myload代理的伺服器</code>
<code> </code><code>if</code> <code>(req.request == </code><code>"GET"</code> <code>&& req.url ~ </code><code>"\.(html|jpg|jpeg)$"</code><code>) {</code>
<code> </code><code>set</code> <code>beresp.ttl = 3600s;</code>
<code>sub vcl_deliver { </code><code>#記錄命中和未命中的變量設定</code>
<code> </code><code>if</code> <code>(obj.hits > 0) {</code>
<code> </code><code>set</code> <code>resp.http.X-Cache = </code><code>"HIT from"</code> <code>+ </code><code>" "</code> <code>+ server.ip;</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>set</code> <code>resp.http.X-Cache = </code><code>"MISS"</code><code>;</code>
<code> </code><code>return</code><code>(deliver);</code>
好了,就寫到這裡吧;感覺這篇文章寫的很不詳細,架構圖也沒有畫,案例也沒有一個個示範,直接上的配置檔案。最近發現自已越來越懶的。前幾天一直學習python,有點學上瘾了。好了,大家晚安。明天周一 都能夠有個好心情。下篇博文會繼續補充。
本文轉自zys467754239 51CTO部落格,原文連結http://blog.51cto.com/467754239/1577216:,如需轉載請自行聯系原作者