varnishhtml
1、簡介
web
Varnish是一款高性能的開源HTTP加速器,挪威最大的在線報紙 Verdens Gang 使用3臺Varnish代替了原來的12臺Squid,性能比之前更好。
正則表達式
Varnish 的做者Poul-Henning Kamp是FreeBSD的內核開發者之一,他認爲如今的計算機比起1975年已經複雜許多。在1975年時,儲存媒介只有兩種:內存與硬盤。但如今計算機系統的內存除了主存外,還包括了CPU內的L一、L2,甚至有L3快取。硬盤上也有本身的快取裝置,所以Squid Cache自行處理物件替換的架構不可能得知這些狀況而作到最佳化,但操做系統能夠得知這些狀況,因此這部份的工做應該交給操做系統處理,這就是 Varnish cache設計架構。express
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。json
2、關於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}
3、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);
# }