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項目是2006年發佈的第一個版本0.9.距今已經八年多了,此文檔之前也提過varnish還不穩定,那是2007年時候編寫的,經過varnish開發團隊和網友們的辛苦耕耘,現在的varnish已經很健壯。很多門戶網站已經部署了varnish,並且反應都很好,甚至反應比squid還穩定,且效率更高,資源佔用更少。相信在反向代理,web加速方面,varnish已經有足夠能力代替squid。
varnish的官網爲https://www.varnish-cache.org,rpm,rpm包的下載位置爲:http://repo.varnish-cache.org。
二、關於Varnish
1.varnish系統架構
varnish主要運行兩個進程:Management進程和Child進程(也叫Cache進程)。
Management進程主要實現應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個命令行接口等。Management進程會每隔一段時間探測一下Child進程以判斷其是否正常運行,如果在指定的時長內未得到Child進程的迴應,Mangagement將會重啓此Child進程。
Child進程包含多種類型的線程,常見的如:
Acceptor進程:接受新的連接請求並響應
worker進程:child進程會爲每個用戶啓動一個worker進程,因此,在高併發的場景中可能會出現數百個worker進程甚至更多
Expiry進程:從緩存中清理過期內容
Varnish依賴“工作區(workspace)”以降低線程在申請或修改內存時出現競爭的可能性。在varnish內部有多種不同的工作區,其中最關鍵的當屬用於管理會話數據的session工作區
2.varnish日誌
爲了與系統的其他部分進行交互,Child進程使用了可以通過文件系統接口進行訪問的共享內存日誌(shared memory log),因此,如果某線程需要記錄信息,其僅需要持有一個鎖,而後向共享內存中的某內存區域寫入數據,再釋放持有的鎖即可。而爲了減少競爭,每個worker線程都使用了日誌數據緩存
共享內存大小一般爲90M,其分爲兩部分,前一部分爲計數器,後半部分爲客戶端請求的數據。varnish通過了多個不同的工具,如varnishlog、varnishncsa或varnishstst等來分析共享內存日誌中的信息並能夠以指定的方式進行顯示
3.varnish的後端存儲
varnish支持多種不同類型的後端存儲。這可以在varnish啓動時使用-s選項指定。後端存儲的類型包括
(1)file:使用特定的文件存儲全部的緩存數據,並通過操作系統的mmap()系統調用整個緩存文件映射至內存區域(如果條件允許)
(2)mallco: 使用mallco()庫調用在varnish啓動時向操作系統申請指定的大小的內存空間以存儲緩存數據
(3)persistent(experimental):與file的功能相同,但是可以持久存儲數據(即重啓varnish時數據不會被清楚),仍處於測試階段
varnish無法追蹤某緩存對象是否存入了緩存文件,而後也就無法得知磁盤上的緩存文件是否可用,因此,file存儲在varnish停止或重啓是會清除數據。而persistent方法的出現對此有一個彌補,但persistent仍處於測試階段,例如目前尚無法有效處理要緩存對象總體大小超出緩存空間的情況,所有,其僅適用於有着巨大緩存空間的場景。
選擇使用合適的存儲方式有助於途勝系統性能,從經驗的角度來看,建議在內存空間足以存儲所有數據的緩存對象時使用malloc的方法,反之,file存儲將會有着更好的性能表現,然而,需要注意的是,varnishd實際上是用的空間比使用-s選項指定的緩存空間更大,一般說來,其需要爲每個緩存對象多使用差不多1k左右的存儲空間,這意味着,對於100萬個緩存對象來說,其使用的緩存空間將超出指定大小1G左右,另外,爲了保存數據結構等,varnish自身也會佔去不少的內存空間。
爲varnish指定使用的緩存類型時,-s選項可接受的參數格式如下:
malloc[,size]或file[,path[,size[,granularity]]]或persistent,path,size{experimental}
三、VCL
1.簡介
VCL(Varnish Configuration Language)是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命令來完成
2.VCL狀態引擎
在VCL狀態引擎中,狀態之間具有相關性,但彼此間互相隔離,每個引擎使用return(x)來退出當前狀態並指示varnish進入下一個狀態
varnish開始處理一個請求時,首先需要分析HTTP請求本身,比如從首部獲取請求方法、驗證其是否爲一個合法的HTTP請求等,當這些基本分析結束後就需要做出第一個決策,即varnish是否從緩存中查找請求的資源,這個決定的實現則需要有VCL來完成,簡單來說,要有vcl_recv方法來完成,如果說管理員沒有定義vcl_recv函數,varnish將會執行默認的vcl_recv函數,然而,即便管理員自定義了vcl_recv,但如果沒有爲自定義的vcl_recv函數指定其終止操作(terminating),其仍將會指定默認的vcl_recv函數,事實上,varnish官方強烈建議讓varnish執行默認的vcl_recv以便處理自定義vcl_recv函數中可能出現的漏洞
3.VCL語法
VCL的設計參考了C和perl語言,因此,對有着C或Perl編程經驗者來說,其非常容易理解。其基本語法說明如下:
(1)//、#或/* comment */用於註釋
(2)sub $name 定義函數
(3)不支持循環,有內置變量
(4)使用終止語句,沒有返回值
(5)域專用
(6)操作符:=(賦值)、==(等值比較)、~(模式匹配)、!(非,取反)、&&(邏輯與)、||(邏輯或)
VCL的函數不接受參數並且沒有返回值,因此,其並非真正意義上的函數,這也限定了VCL內部的數據傳遞只能隱藏在HTTP首部內部進行。VCL的return語句用於將控制權從VCL狀態引擎返回給varnish,而非默認函數,這就是爲什麼VCL只有終止語句而沒有返回值的原因,同時,對於每個“域”來說,可以定義一個或多個終止語句,以告訴varnish下一步採取何種操作,如查詢緩存或不查詢緩存
4.VCL的內置函數
VCL提供了結果函數來實現字符串的修改,如添加bans,重啓VCL狀態引擎因將控制權轉回varnish等
regsub(str,reget,sub):基於正則表達式搜索指定的字符串並將其替換成指定的字符串,只替換匹配到的第一個
regsuball(str,reget,sub):基於正則表達式搜索指定的字符串並將其統統替換成指定的字符串
ban(expression):
ban_url(regex):Bans所有其URL能夠由regex匹配的緩存對象
purge:從緩存中挑選出某對象以及其相關變種一併刪除,這可以通過通過HYTP協議的PURGE方法完成
hash_data(str):
return():當某個VCL與運行結束時,將控制權返回給Varnish,並指示Varnish如何進行後續的操作:其可以返回的指令包括:lookup、pass、pipe、hit_for_pass、fetch、deliver和hash等:但某特定域可能技能返回某些特定的指令,而非前面列出的全部指令:
return(restart):重新運行整個VCL,即重新從vcl_recv開始進行處理;每一次重啓都會增加req.restaets變量中的值,而max_restaets參數則用於限定最大重啓次數
5.vcl_recv
vcl_recv是在varnish完成對請求報文的解碼爲基本數據結構後第一個要指定的子例程,他通常有四個主要用途:
(1)修改客戶端數據以減少緩存對象差異性,比如刪除URL中的www.等字符串
(2)基於客戶端數據選用緩存策略:比如僅緩存特定的額URL請求、不緩存POST請求等
(3)爲某web應用程序執行URL重寫
(4)挑選合適的後端服務器;
可以使用下面的終止語句,即通過return()向varnish返回指示操作
pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;
pipe:不對客戶端進行檢查或做出任何操作,而是在客戶端與後端服務器之間建立專業“通道”,並直接將數據在二者之間進行傳送:此時,keep-alive連接中後續傳送的數據也都將在通過此管道進行直接傳送,並不會出現在任何日誌中
lookup:在緩存中查找用戶請求的對象,如果緩存中沒有其指定的對象,後續操作很可能會將其請求的對象進行緩存
error:有varnish自己合成一個響應報文,一般是響應一個錯誤類信息、重定向類信息或緩存均衡器返回的後端web服務器健康狀態檢查類信息
vcl_recv也可以通過精巧的策略完成一定意義上的安全功能,以將某特定的***扼殺於搖籃中,同時,它也可以檢查出一些拼寫的錯誤並將其進行修改
varnish默認的vcl_recv專門設計用來實現安全的緩策略,它主要完成兩種功能:
(1)僅處理可以識別的HTTP方法,並且只緩存GET和HEAD方法
(2)不緩存任何用戶特有的數據
安全起見,一般都在自定義的vcl_recv中不要使用return()終止語句,而是再由默認vcl_recv進行處理,並有其做出響應的的處理決策
6.vcl_fetch
如前面所述,想對於vcl_recv是根據客戶端的請求做出緩存策略來說,vcl_fetch則是根據服務器端的響應做出緩存決策,在任何VCL狀態引擎中發揮pass操作都將有vcl_fetch進行後續處理。vcl_fetch中有許多可用的內置變量,比如最常見的用於定義某對象緩存時長的beresp.ttl變量,通過return()返回給varnish的操作指令有:
deliver:緩存此對象,並將其發送給客戶端(經由vcl_deliver)
hit_for_pass:不緩存此對象,但可以導致後續對此對象的請求直接送達到vcl_pass進行處理
restart:重啓整個VCL,並增加重啓次數,超出max_restarts限定的最大重啓次數將會發揮錯誤信息
error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。
默認的vcl_fetch放棄了緩存任何使用了Set-Cookie首部的響應
7.vcl_deliver
在緩存中找到緩存內容,發送給客戶端時調用此參數,通過return()返回給varnish的操作指令有:
deliver:緩存此對象,並將其發送給客戶端(經由vcl_deliver)
error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。
8.val_pass
此函數在進入pass模式時被調用,用於將請求直接傳遞至後端主機,後端主機應答數據後發送給客戶端,但是不緩存任何數據,在當前連接下,每次都是犯回最新的內容,通過return()返回給varnish的操作指令有:
error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。
pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;
9.vcl_pipe
不對客戶端進行檢查或做出任何操作,而是在客戶端與後端服務器之間建立專業“通道”,並直接將數據在二者之間進行傳送:此時,keep-alive連接中後續傳送的數據也都將在通過此管道進行直接傳送,並不會出現在任何日誌中,通過return()返回給varnish的操作指令有:
error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。
pipe:不對客戶端進行檢查或做出任何操作,而是在客戶端與後端服務器之間建立專業“通道”,並直接將數據在二者之間進行傳送:此時,keep-alive連接中後續傳送的數據也都將在通過此管道進行直接傳送,並不會出現在任何日誌中
10.lookup
表示在緩存裏查找被請求的對象,並且根據查找的數據把控制權交給vcl_miss或vcl_hit
11.vcl_hit
在執行lookup指令後,如果在緩存中找到請求的內容,將自動調用此函數,通過return()返回給varnish的操作指令有:
deliver:緩存此對象,並將其發送給客戶端(經由vcl_deliver)
error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。
pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;
12.vcl_miss函數
在執行lookup指令後,如果在緩存中找不到請求的內容,將自動調用此函數,此函數可以判斷是否在後端服務器上獲取內容,通過return()返回給varnish的操作指令有:
error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。
pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;
13.VCL處理流程圖
通過上面對VCL函數的介紹,大家應該對每個函數實現的功能有一個瞭解,,起始每個函數之間是有聯繫的,如下圖所示
狀態引擎:
1:vcl_recv 2:vcl_pipe 3:vcl_pass 4:vcl_hash 5:vcl_hit 6:vcl_miss 7:vcl_fetch 8:vcl_delier
9:vcl_error
緩存的處理步驟:
接受請求---解析請求---查詢緩存---新鮮度檢查---創建響應報文---發送響應---記錄日誌
緩存的新鮮度檢測方法:
(1)過期時間:
HTTP/1.0
Expires:"Mon, 21 Mar 2016 05:02:19 GMT" 固定時間來檢測
HTTP/1.1
Cache-Control:"max-age=900" 這種最多存活時時間來檢測
(2)有效性再驗證:revalidate
如果原始內容發生改變,就正常響應,響應碼200
如果原始內容沒改變,則僅相應首部(不帶body部分),相應碼304(Not Modified)
如果原始內容消失,響應爲404,些時緩存中cache object 也應該被刪除
(3)條件式請求首部:
根據時間戳判斷:
If-Modified-Since: 自從請求的時間之後,請求的資源是否發生過修改,用時間戳驗證
If-Unmodified-Since:自從請求的時間之後,請求的資源是否發沒有修改
根據標籤來判斷:
If-None-Match :本地緩存中存儲的文檔的Etag標籤是否與服務器文檔的Etag不匹配。
If-Match :本地緩存中存儲的文檔的Etag標籤是否與服務器文檔的Etag匹配。
yum 安裝 varnish
# yum insatll varnish-libs-3.0.4-1.el6.x86_64.rpm varnish-3.0.4-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-3.0.5-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-libs-3.0.5-1.el6.x86_64.rpm
wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-docs-3.0.5-1.el6.x86_64.rpm
1:
# vi /etc/sysconfig/
var
nish
修改一下參數
VARNISH_LISTEN_PORT=80 //表示將varnish對外的監聽端口改爲80 VARNISH_STORAGE="malloc,100M"
//將數據緩存在內存中,內存大小爲100M
其餘的使用默認即可
2:
配置varnish
本處使用varnishadm命令行接口來刷新varnish
命令格式:varnishadm [-n ident] [-t timeout] [-S secretfile] -T [address]:port command [...]
通過命令行的方式連接至varnishd進行管理操作的工具,指定要連接的varnish實例有兩種方法:
-T [address]:port 來接指定套接字上的實例
-n ident 連接指定名稱的實例
其運行模式有兩種,當不在命令行中給出指定要指定的“command”時,要將進入交互模式,否則,varnish將指定指定的“command”並退出。
# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnishadm 使用:
vcl.load
vcl.use
vcl.show
vcl.discard
varnish 一般只對 get head 緩存
backend storage:支持緩存存儲內型有3種
-s type
malloc [,size] //內存中緩存
file[,path[,size[,granularity]]] //一個文件保存所有緩存
persistent,path,size {experimental} // 在具體生並環境中不建議用,
在varnishl 裏可用單分支和多分支判斷
varnish 裏可用變量:
1:常用變量,在任何引擎中都可以用的,
new // 獲取當前系統的當前時間
.host //後端主機的ip
.port //後斷主機的端口
2:用於處理請求階段
client.ip // 客戶機ip
server.hostname // 服務器主機名(varnish服務器名)
server.ip // 服務器主ip (varnish ip)
server.port //服務器端口 (varnish 端口)
req.request //請求方法
req.url // 請求url
req.porto //請求協議
req.backend //用於服務此次請求的後端主機
req.backend.healthy //後端健康狀態
req.http.HEADER //引用請求報文中指定的首部
req.hash-always_miss
req.hash-ignore_busy
req.can_gzip //客戶端是否能接受gzip 壓縮的內容
req.restarts //此請求被重啓的請求
3: varnish自己 向backend 主機發起請求前可用的變量
bereq.request //varnish 對後端口請求方法
bereq.url //varnish 對後端口請求url
bereq.proto //varnish 對後端請求協議
bereq.http.HEADER //varnish 對後端口請求頭
bereq.connect_timeout //等待與backend主機發起的連接超時時長
4:backend主機的響應報文到達varnish主機後,將其放放置於cache中之前可用的變量。
beresp.do_stream // 流式響應
beresp.do_gzip // 是否壓縮後存入cache
beresp.do_gunzip // 是否解壓後存入緩存。
beresp.http.HEADER // 響應時頭
beresp.proto // 響應時協議
beresp.status // 響應狀態碼
beresp.response // 響應時的原因短語
beresp.ttl // 響應對象的剩餘生存時長,單位爲秒
beresp.backend.name // 相應報文來源的backend名稱
beresp.backend.ip // 響應時報文來源的backend IP
beresp.backend.port // 響應時報文來源的backend 端口
beresp.storage //響應的存儲後端
5:緩存對象存入的ccache之後可用的變量
obj,proto //響應時協議
obj.status // 響應時狀態碼
obj.response
obj.hits //響應時次數
obj.ttl
obj,http,HEADER // 響應首部
6:在決定對請求鍵做hash計算時可用的變量
req.hash
7:在爲客戶端準備響應時報文可用變量
resp.proto
resp.status
resp.response
resp.http.HEADER
狀態引擎:
vcl_init: 在裝載vcl,用其處理請求之前
vcl_recv: 請求被接入,但在其分析,處理完成之前。
是否服務些請求,如何服務,使用那個後端主機服務
vcl_fetch:從後端口主機收到相應報文之前被調用
deliver
error code 給個錯誤碼
restart 重啓請求
warnish 的param的查看和修改:
varnish> param.show -l
修改鏈接池一些值,但是這種方法只對當前有效果
varnish> param.set thread_pool_max 4000 修改線程池個數
200
varnish 線程模型:
cache-worker 線程
cache-mian 線程:些線程只有一個,用來啓動cache
ban luker:
acceptor:
epoll: 線程池管理
expire: 清理過期緩存
thread_pool_add_delay 2 [milliseconds]
thread_pool_add_threshold 2 [requests]
thread_pool_fail_delay 200 [milliseconds]
thread_pool_max 3000 [threads] 單個線程池啓動最多線程個數
thread_pool_min 50 [threads]
thread_pool_purge_delay 1000 [milliseconds] 每一秒清理一次緩存,請保留默認
thread_pool_stack unlimited [bytes]
thread_pool_timeout 120 [seconds] 線程池的超時時間,
thread_pool_workspace 65536 [bytes] 線程池默認使用多少內存,建議默認
thread_pools 2 [pools] 線程池管理
thread_stats_rate 10 [requests]
varnish的命令行工具:
(1)varnishadm
(2)varnishtop:內存日誌區域查看工具
RxHeader User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebK
it/53
RxHeader:爲tag,基於標籤過慮,可用-i或-x 選項,
User-Agent 爲起始內容。稱爲日誌消息。用-I或-X過濾
-I regexp:僅顯示被模式匹配到的條目
-X regexp:僅顯示不被模式匹配到的條目
-C:忽略大小寫
-d:顯示已有日誌
(3)varnishstat 緩存統計
-l 列出所有字段
-f 統計字段 -f後接的字段名
-x:xml輸出格式
-j:json 格式輸出
配置文件:
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
return (deliver);
}
下面爲varnish 配置樣本
backend default {
.host = "192.168.1.105";
.port = "80";
}
acl purgers {
"127.0.0.1";
"192.168.1.0"/24;
}
#
# Below is a commented-out copy of the default VCL logic. If you
# redefine any of these subroutines, the built-in logic will be
# appended to your code.
sub vcl_recv {
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
if (req.request == "PURGE") {
if (!client.ip ~ purgers) {
error 405 "Method not allowed";
}
return (lookup);
}
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE" &&
req.request != "PURGE") {
# /* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD" && req.request !="PURGE") {
# /* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
# /* Not cacheable by default */
return (pass);
}
return (lookup);
}
# sub vcl_pipe {
# # Note that only the first request to the backend will have
# # X-Forwarded-For set. If you use X-Forwarded-For and want to
# # have it set for all requests, make sure to have:
# # set bereq.http.connection = "close";
# # here. It is not set by default as it might break some broken web
# # applications, like IIS with NTLM authentication.
# return (pipe);
# }
#
sub vcl_pass {
if (req.request == "PURGE") {
error 502 "PURGE on a passed object";
}
return (pass);
}
#
# sub vcl_hash {
# hash_data(req.url);
# if (req.http.host) {
# hash_data(req.http.host);
# } else {
# hash_data(server.ip);
# }
# return (hash);
# }
#
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "Purged";
}
return (deliver);
}
sub vcl_miss {
if (req.request == "PURGE") {
purge;
error 404 "Not in cache";
}
return (fetch);
}
# sub vcl_fetch {
# if (beresp.ttl <= 0s ||
# beresp.http.Set-Cookie ||
# beresp.http.Vary == "*") {
# /*
# * Mark as "Hit-For-Pass" for the next 2 minutes
# */
# set beresp.ttl = 120 s;
# return (hit_for_pass);
# }
# return (deliver);
# }
#
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
return (deliver);
}
# sub vcl_error {
# set obj.http.Content-Type = "text/html; charset=utf-8";
# set obj.http.Retry-After = "5";
# synthetic {"
# <?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>"} + obj.status + " " + obj.response + {"</title>
# </head>
# <body>
# <h1>Error "} + obj.status + " " + obj.response + {"</h1>
# <p>"} + obj.response + {"</p>
# <h3>Guru Meditation:</h3>
# <p>XID: "} + req.xid + {"</p>
# <hr>
# <p>Varnish cache server</p>
# </body>
# </html>
# "};
# return (deliver);
# }
#
# sub vcl_init {
# return (ok);
# }
#
# sub vcl_fini {
# return (ok);
配置範例2:
probe chk {
.url = "/test.html";
.window = 5;
.threshold = 3;
.interval = 3s;
.timeout = 1s;
}
backend web1 {
.host = "192.168.1.104";
.port = "80";
.probe = chk;
}
backend web2 {
.host = "192.168.1.105";
.port = "80";
.probe = chk;
}
director webservers random {
.retries = 5;
{
.backend = web1;
.weight = 1;
}
{
.backend = web2;
.weight = 1;
}
}
#
#
acl purgers {
"127.0.0.1";
"192.168.1.0"/24;
}
# Below is a commented-out copy of the default VCL logic. If you
# redefine any of these subroutines, the built-in logic will be
# appended to your code.
sub vcl_recv {
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
if (req.request ~ "test.html") {
set req.backend = web1;
} else {
set req.backend = webservers;
}
if (req.request == "PURGE") {
if (!client.ip ~ purgers) {
error 405 "Method not allowed";
}
return (lookup);
}
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE" &&
req.request != "PURGE") {
# /* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD" && req.request !="PURGE") {
# /* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
# /* Not cacheable by default */
return (pass);
}
return (lookup);
}
# sub vcl_pipe {
# # Note that only the first request to the backend will have
# # X-Forwarded-For set. If you use X-Forwarded-For and want to
# # have it set for all requests, make sure to have:
# # set bereq.http.connection = "close";
# # here. It is not set by default as it might break some broken web
# # applications, like IIS with NTLM authentication.
# return (pipe);
# }
#
sub vcl_pass {
if (req.request == "PURGE") {
error 502 "PURGE on a passed object";
}
return (pass);
}
#
# sub vcl_hash {
# hash_data(req.url);
# if (req.http.host) {
# hash_data(req.http.host);
# } else {
# hash_data(server.ip);
# }
# return (hash);
# }
#
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "Purged";
}
return (deliver);
}
sub vcl_miss {
if (req.request == "PURGE") {
purge;
error 404 "Not in cache";
}
return (fetch);
}
# sub vcl_fetch {
# if (beresp.ttl <= 0s ||
# beresp.http.Set-Cookie ||
# beresp.http.Vary == "*") {
# /*
# * Mark as "Hit-For-Pass" for the next 2 minutes
# */
# set beresp.ttl = 120 s;
# return (hit_for_pass);
# }
# return (deliver);
# }
#
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
return (deliver);
}
# sub vcl_error {
# set obj.http.Content-Type = "text/html; charset=utf-8";
# set obj.http.Retry-After = "5";
# synthetic {"
# <?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>"} + obj.status + " " + obj.response + {"</title>
# </head>
# <body>
# <h1>Error "} + obj.status + " " + obj.response + {"</h1>
# <p>"} + obj.response + {"</p>
# <h3>Guru Meditation:</h3>
# <p>XID: "} + req.xid + {"</p>
# <hr>
# <p>Varnish cache server</p>
# </body>
# </html>
# "};
# return (deliver);
# }
#
# sub vcl_init {
# return (ok);
# }
#
# sub vcl_fini {
# return (ok);
# }