一、Web緩存
1.web緩存
web緩存是可以自動儲存常見文檔副本的HTTP裝置。當Web請求抵達緩存時,如果本地有"已緩存的"副本,可以從本地的儲存設備而不是原始伺服器裝置中提取這個文檔。
通過key-value鍵值方式緩存,key中儲存了URL路徑,value中儲存了web内容,其均使用hash格式,算法保證能在海量資料中快速命中緩存内容
(1)緩存優點
1) 減少備援的資料傳輸,節省帶寬
2) 緩解網絡瓶頸問題,無需耕宇寬帶就能更快的加載頁面
3) 降低對原始伺服器的要求,伺服器可以更快的響應避免過載
4) 降低了距離時延
(2)相關術語
緩存命中
cache hit,可以用已有的副本為某些到達緩存的請求提供服務
緩存未命中
cache miss,無緩存命中副本,被轉向後端原始伺服器
HTTP再驗證
revalidation,新鮮度檢測,緩存副本和原始伺服器上的資料要不時的進行檢測是否為最新
命中率
cache hit rate,緩存提供服務的請求所占的比例,命中率在0-1之間,通常用百分數描述
注意:
1) 命中率可以分為:文檔命中率(從文檔個數進行衡量)、位元組命中率(從内容大小進行衡量)
2) 緩存對象由其生命周期,需要定期清理
3)當緩存空間耗盡,會采用LRU(最近最少使用算法)進行覆寫
4)不是所有的資料都能夠緩存,如首部Authorization、Cookie、Vary:accept-encoding= … ...
(3)緩存處理的步驟:
接收請求 -->解析請求(提取請求的URL及各種首部) --> 查詢緩存 --> 新鮮度檢測 --> 建立響應封包--> 發送響應 --> 記錄日志
2.HTTP首部緩存控制機制
Cache-Control: no-store禁止緩存對響應進行複制
Cache-Control: no-cache可以存儲在本地緩存區域中,隻是在于原始伺服器進行新鮮度在驗證之前緩存不能提供給用戶端使用
Cache-Control:must-revalidate嚴格遵循過期資訊,在實作沒和伺服器再驗證不提供對象舊的副本。新鮮度檢測失敗傳回504
Cache-Control: max-age讀秒,僅适用于公共緩存
Expries日期首部到響應中,指明具體時間,不推薦使用
不添加過期資訊,讓緩存确定自己的過期日期
(1)新鮮度檢測機制
在HTTP協定的封包首部會對web作出首部定義,通過首部的封包對比來做新鮮度檢測。HTTP/1.0 Expires定義的是絕對時間,當達到指定的日期時間的時候,緩存失效;HTTP/1.1 Cache-Control:max-age=#定義的是相對時間,記秒,已解決HTTP/1.0協定在解決全球性資料緩存檢測時各地區時差産生的問題
執行個體:
HTTP/1.0 Expires:Thu, 04 Jun 2015 23:38:18 GMT
HTTP/1.1Cache-Control:max-age=600
(2)有效性再驗正:revalidate
如果原始内容未改變,則僅響應首部(不附帶body部分),響應碼304(Not Modified)
如果原始内容發生改變,則正常響應,響應碼200;
如果原始内容消失,則響應404,此時緩存中的cacheobject也應該被删除;
說明:
相關條件式請求首部:If-Modified-Since、If-Unmodified-Since、If-Match、If-None-Match:
If-Modified-Sicce:<date>
如果從指定日期之後文檔被修改了,就執行請求的方法。可以與Last-Modified(最後被修改)伺服器響應首部配合使用,隻有在内容被修改後與已緩存版本有所不同時候采取擷取内容
If-None_Match:<tags>
标簽,如果一緩存标簽與伺服器文檔中的标簽不同,If-None_Match首部就會執行請求的方法
HTTP緩存封包執行個體:
Cache-Control = "Cache-Control" ":"1#cache-directive
cache-directive = cache-request-directive
| cache-response-directive
cache-request-directive =
"no-cache"
| "no-store" (backup)
| "max-age" "="delta-seconds
| "max-stale" ["=" delta-seconds ]
| "min-fresh" "="delta-seconds
| "no-transform"
| "only-if-cached"
| cache-extension
cache-response-directive =
"public"
| "private" [ "="<"> 1#field-name <"> ]
| "no-cache" [ "="<"> 1#field-name <"> ]
| "no-store"
| "no-transform"
| "must-revalidate"
| "proxy-revalidate"
| "max-age" "="delta-seconds
| "s-maxage" "="delta-seconds
| cache-extension
3.常見的緩存服務開源解決方案
軟體
存儲模式
性能
配置複雜度
purge效率
共享存儲
squid
硬碟
較高
簡單
低
可以并聯,但是配置複雜
varnish
硬碟/記憶體
高
比較簡單
不能
說明:
Squid,很古老的反向代理軟體,擁有傳統代理、身份驗證、流量管理等進階功能,但是配置太複雜。優勢在于完整的龐大的cache技術資料。Squid在大規模負載均衡場景下很穩定
Varnish是新興的一個軟體,設計簡單,基于記憶體緩存,重新開機後資料将消失。
(1)varnish對比squid的優點
1)varnish穩定性很高,兩者在完成相同負荷的工作時,squid伺服器發生故障的幾率要高于varnish,因為squid要經常重新開機
2)varnish通路速度更快,其采用了"Visual PageCache"技術,所有緩存資料都直接從記憶體中讀取,而squid是從硬碟讀取,因而varnish在通路速度方面會更快
3)varnish可支援更多并發連接配接,因為varnish的TCP連接配接釋放要比squid快,因而在高并發連接配接情況下可以支援更多TCP連接配接
4)varnish可以通過管理端口,使用正規表達式批量的清除部分緩存,而squid是做不到的。
5)squid屬于單程序使用單核CPU,但Varnish是通過fork形式打開多程序來做處理,是以是合理的使用所有核來處理相應的請求
(2)varnish對比squid的缺點
1)varnish程序一旦Hang、Crash或者重新開機,緩存資料都會從記憶體中完全釋放,此時所有請求都會發送到後端伺服器,在高并發情況下,會給後端伺服器造成很大的壓力
2)在varnish使用中,如果單個vrl的請求通過HA/F5,每次請求不同的varnish伺服器時,被請求的varnish伺服器都會被穿透到後端,而同樣的請求會在多台伺服器上緩存,也會造成varnish的緩存資源浪費,也會造成性能下降
二、Varnish緩存概述
1.varnish程式架構
varnish是高性能開源反向代理伺服器,http加速器。官方網址:www.varnish-cache.org。版本:v2,v3,v4
架構圖:
主要運作兩個程序:Management程序和Child(Cache)程序
(1) Management管理程序
主要實作應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個指令行接口等。Management程序會定期探測Child程序。若在指定時長未得到Child程序回應,會重新開機此Child程序。
配置檔案是VCL程式設計語言格式,定義緩存工作功能的,VCL編譯器需要調用C編譯器編譯後成varnish能加載的格式才能使用
(2) Child(Cache)程序
Child程序包含多種類型的線程,主要用于使用者請求管理和緩存管理
Acceptor:接收器,接收新的連接配接請求并響應;
Worker:處理使用者請求
Expiry:從緩存中清理過期緩存内容;
cache-worker線程
cache-main線程:此線程隻有一個,用于啟動caceh;
ban luker:緩存清理線程
acceptor:接收線程
epoll:線程池管理器
expire:清理過期緩存
注意:
Varnish依賴“工作區(workspace)”以降低線程在申請或修改記憶體時出現競争的可能性。在varnish内部有多種不同的工作區,其中最關鍵的當屬用于管理會話資料的session工作區。
(3) VCL和C編譯器
VCL編寫的緩存政策儲存至.vcl檔案中,其需要編譯成二進制的格式後才能由varnish調用。
VCL政策在啟用前,會由management程序将其轉換為C代碼,而後再由gcc編譯器将C代碼編譯成二進制程式。編譯完成後,management負責将其連接配接至varnish執行個體,即child程序。
(4) 調用接口
CLIInterface(指令行接口)、telent Interface(文本協定不安全)、web Interface(商業)
(5) varnish log file日志
1) 共享記憶體日志(shared memory log):日志儲存在記憶體中的共享空間,大小一般為90M,其分為兩部分,前一部分為計數器,後半部分為用戶端請求的資料。如果某線程需要記錄資訊,其僅需要持有一個鎖,而後向共享記憶體中的某記憶體區域寫入資料,再釋放持有的鎖
2) varnish log在記憶體中實作日志儲存,預設不能長久儲存,會循環儲存
3) varnish提供多個工具如varnishlog、varnishncsa或varnishstat等來分析共享記憶體日志中的資訊并以指定的方式進行顯示。
2.VCL:配置緩存政策工具
Varnish Configuration Language (VCL):
(1)基于“域”(domain specific)的簡單程式設計語言
(2)支援有限的算術運算和邏輯運算操作
(3)允許使用正規表達式進行字元串比對
(4)允許使用者使用set自定義變量
(5)支援if判斷語句
(6)支援内置的函數和變量等。
3.varnish存儲類型
(1)file:單個檔案;不支援持久機制
使用特定的檔案存儲全部的緩存資料,并通過作業系統的mmap()系統調用将整個緩存檔案映射至記憶體區域
(2)malloc:記憶體方式
使用malloc()庫調用在varnish啟動時向作業系統申請指定大小的記憶體空間以存儲緩存對象;
(3)persistent(experimental):基于檔案的持久存儲
與file的功能相同,但可以持久存儲資料(即重新開機varnish資料時不會被清除);仍處于測試期;
注意:
1) file存儲方法在varnish停止或重新開機時會清除資料:varnish無法追蹤某緩存對象是否存入了緩存檔案
2) persistent僅适用于有巨大緩存空間的場景,目前尚無法有效處理要緩存對象總體大小超出緩存空間的情況,
3) 建議在記憶體空間足以存儲所有的緩存對象時使用malloc的方法,反之,file存儲将有着更好的性能的表現。
4) 對于100萬個緩存對象的場景來說,其使用的緩存空間将超出指定大小1G左右。另外,為了儲存資料結構等,varnish自身也會占去不小的記憶體空間。
三、安裝啟動varnish服務
1.安裝相關程式包
[root@localhost ~]#yum install -y gcc varnish-3.0.4-1.el6.x86_64.rpm varnish-docs-3.0.4-1.el6.x86_64.rpmvarnish-libs-3.0.4-1.el6.x86_64.rpm varnish-libs-devel-3.0.4-1.el6.x86_64.rpm
說明:
1) gcc編輯器是varnish編譯val語言所需的依賴元件
2) varnish提供程式的主包、varnish-libs提供程式相關的庫,必須安裝
3) varnish-libs-devel提供二次開發所依賴的庫檔案、varnish-docs提供varnish幫助文檔,可以視情況安裝
2.配置varnish啟動時腳本配置檔案/etc/sysconfig/varnish
[root@localhost ~]# vim /etc/sysconfig/varnish
NFILES=131072
打開的最大檔案數
MEMLOCK=82000
鎖定共享記憶體大小
NPROCS="unlimited"
最大線程數,無限制
RELOAD_VCL=1
自動重新裝載緩存政策,1表示腳本啟動自動重新裝載緩存政策配置檔案
VARNISH_VCL_CONF=/etc/varnish/default.vcl
預設的緩存政策配置檔案
VARNISH_LISTEN_PORT=6081
預設監聽端口,一般改為80端口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
管理者management程序管理位址
VARNISH_ADMIN_LISTEN_PORT=6082
管理者management程序管理端口
VARNISH_SECRET_FILE=/etc/varnish/secret
啟動裝載的密鑰檔案位置,域共享密鑰
VARNISH_MIN_THREADS=50
最少線程,啟動時最騷啟動的空閑程序
VARNISH_MAX_THREADS=1000
最大啟動程序,最多不能超過5000個并發
VARNISH_THREAD_TIMEOUT=120
線程逾時時長
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin
緩存檔案存放檔案(二進制檔案)
VARNISH_STORAGE_SIZE=1G
緩存大小
VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"
緩存類型和大小
VARNISH_TTL=120
當後端主機不是指定的時候使用逾時時長
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
-f ${VARNISH_VCL_CONF} \
-T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
-t ${VARNISH_TTL} \
-w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
-u varnish -g varnish \
-S ${VARNISH_SECRET_FILE} \
-s ${VARNISH_STORAGE}"
注意:
以下配置必須修改:VARNISH_LISTEN_PORT=80,一般改為80端口,響應http請求,做為web緩存
VARNISH_STORAGE,一般在大規模圖檔緩存時候可以為file,但時硬體上最好是固态硬碟
3.啟動服務
[root@localhost~]# service varnish start
四、varnish指令行管理工具
1.varnishadm:登入指令行終端
指令文法:varnishadm[-t timeout] [-S secret_file] [-T address:port] [-n name] [command [...]]
[root@localhost~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
varnish> help
vcl.list
檢視配置檔案
vcl.load
重新編譯加載vcl配置,需要指明自定義版本名稱,和需要編譯的檔案default.vcl位置(相對)
vcl.use
使用編譯的配置檔案,指明自定義版本名稱
vcl.show
顯示指定的配置檔案詳細資訊,指明自定義版本名稱
vcl.discard
手動清理版本,否則舊版本配置資訊會在varnish重新開機後丢棄
2.varnish的param(參數)檢視及設定
param.show[-l] [param]
param.set[param] [value]
varnish通過線程池模型定義其最大并發連接配接數:
thread_pools
線程池個數;預設為2;
thread_pool_max
單個線程池内允許啟動的最多線程個數;
thread_pool_min
啟動時要啟動的線程數;
thread_pool_purge_delay
清理線程的時間長度,最小不能100毫秒
thread_pool_stack
工作線程棧,預設為-1,unlimited,不做限制
thread_pool_timeout
逾時時長,多于thread_pool_min的線程空閑此參數指定的時長後即被purge
thread_pool_wokerspace
工作空間,預設使用記憶體65536位元組
3.varnishtop: 記憶體日志區域檢視工具
-Iregexp: 僅顯示被模式比對到的條目
-Xregexp:僅顯示不被模式比對到的條目
-C:忽略字元大小寫;
-d:顯示已有日志;
varnish>varnishtopUser-Agent
顯示結果執行個體:
RxHeader User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/43.0.2357.81 Safari/537.36
說明:
RxHeader:稱為tag,基于tag過濾,可使用-i或-x選項;
User-Agent起始的内容:稱為日志資訊,可使用-I或-X選項進行過濾;
4.varnishstat:varnish資料統計工具
-f field, field, …:指明顯示的字段
-l:列出所有可用字段
-x:xml輸出格式
-j:json輸出格式
五、VCL狀态引擎制定緩存政策
1.varnish狀态引擎
varnish内部有幾個所謂的狀态(state),在這些狀态上可以附加通過VCL定義的政策以完成相應的緩存處理機制,是以VCL也經常被稱作“域專用”語言或狀态引擎,“域專用”指的是有些資料僅出現于特定的狀态中。
狀态之間具有相關性,但彼此間互相隔離,每個引擎使用return(x)來退出目前狀态并訓示varnish進入下一個狀态。
(1)狀态引擎分類
vcl_recv、vcl_hash、vcl_hit、vcl_miss、vcl_fetch、vcl_deliver、vcl_pipe、vcl_pass、vcl_error
vcl_init
在裝載vcl,用其處理任何請求之前
vcl_recv
請求被接入,但在其被分析、處理完成之前;是否服務此請求、如何服務、使用哪個後端主機為其服務
vcl_pipe
方法不了解
vcl_pass
不查詢緩存
vcl_hash
查找緩存,調用内置hash_data()函數,決定對什麼内容hash計算,如後端存在虛拟主機,但用ip通路不能命中
vcl_hit
命中
vcl_miss
未命中
vcl_fetch
在後端伺服器取内容,其能讓可緩存或不緩存。從後端主機收到響應封包之前會被調用,傳回的值可以為deliver、error code [reason]、hit_for_pass、restart
vcl_deliver
傳送
vcl_error
錯誤處理機制
(2)狀态引擎工作流程(v3):
varnish先對HTTP請求本身進本分析,再由vcl_recv方法完成決策(是否在緩存中查詢請求額資源)
vcl_recv--> vcl_hash --> vcl_hit --> vcl_deliver
vcl_recv--> vcl_hash --> vcl_miss --> vcl_fetch --> vcl_deliver
vcl_recv--> vcl_pass --> vcl_fetch --> vcl_deliver
vcl_recv--> vcl_pipe
(3)vcl_recv引擎
vcl_recv是在Varnish完成對請求封包的解碼為基本資料結構後第一個要執行的子例程,它通常有四個主要用途:
1)修改用戶端資料以減少緩存對象差異性;比如删除URL中的www.等字元;
2)基于用戶端資料選用緩存政策;比如僅緩存特定的URL請求、不緩存POST請求等;
3)為某web應用程式執行URL重寫規則;
4)挑選合适的後端Web伺服器;
可以通過return()向Varnish傳回的訓示操作:
pass:繞過緩存,即不從緩存中查詢内容或不将内容存儲至緩存中;
pipe:不對用戶端進行檢查或做出任何操作,而是在用戶端與後端伺服器之間建立專用“管道”,并直接将資料在二者之間進行傳送;此時,keep-alive連接配接中後續傳送的資料也都将通過此管道進行直接傳送,并不會出現在任何日志中;
lookup:在緩存中查找使用者請求的對象,如果緩存中沒有其請求的對象,後續操作很可能會将其請求的對象進行緩存;
error:由Varnish自己合成一個響應封包,一般是響應一個錯誤類資訊、重定向類資訊或負載均衡器傳回的後端web伺服器健康狀态檢查類資訊;
注意:
1) Varnish預設的vcl_recv專門設計用來實作安全的緩存政策,它主要完成兩種功能:
a)僅處理可以識别的HTTP方法,并且隻緩存GET和HEAD方法;
b)不緩存任何使用者特有的資料;
2) 一般自定義vcl_recv中不要使用return()終止語句,而是再由預設vcl_recv進行處理,并由其做出相應的處理決策。
#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 != "GET"&&
# req.request != "HEAD"&&
# req.request != "PUT"&&
# req.request != "POST"&&
# req.request != "TRACE"&&
# req.request != "OPTIONS"&&
# req.request != "DELETE") {
# /* Non-RFC2616 or CONNECT which isweird. */
# return (pipe);
# if (req.request != "GET"&& req.request != "HEAD") {
# /* We only deal with GET and HEAD bydefault */
# return (pass);
# if (req.http.Authorization ||req.http.Cookie) {
# /* Not cacheable by default */
# return (lookup);
#}
(3)vcl_fetch引擎
vcl_fetch是根據伺服器端的響應作出緩存決策。在任何VCL狀态引擎中傳回pass操作都将由vcl_fetch進行後續處理。預設的vcl_fetch放棄了緩存任何使用了Set-Cookie首部的響應。通過return()傳回給varnish的操作訓示有:
1)deliver:緩存此對象,并将其發送給用戶端(經由vcl_deliver);
2)hit_for_pass:不緩存此對象,但可以導緻後續對此對象的請求直接送達到vcl_pass進行處理;
3)restart:重新開機整個VCL,并增加重新開機計數;超出max_restarts限定的最大重新開機次數後将會傳回錯誤資訊;
4)errorcode [reason]:傳回指定的錯誤代碼給用戶端并丢棄此請求;
2.VCL程式設計語言文法
(1) //, #, /* */用于注釋;會被編譯器忽略;
(2) sub $name定義函數,不接受參數;VCL内部的資料傳遞隻能隐藏在HTTP首部内部進行
(3) 不支援循環語句;
(4)有衆多内置的變量,變量的可調用位置與state engine有密切相關性;
(5)支援終止語句,return(action);沒有傳回值;
(6) "域"專用語言,隻能用在特定的域上;
(7) 支援衆多操作符:=(指派)、==(等值比較)、~(模式比對)、!(取反)、&&(邏輯與)、||(邏輯或)
(8) 一般為條件判斷語句:單分支、雙分支、多分支
3.varnish内置函數
(1)regsub(str,regex,sub)
regsuball(str,regex,sub):這兩個用于基于正規表達式搜尋指定的字元串并将其替換為指定的字元串;但regsuball()可以将str中能夠被regex比對到的字元串統統替換為sub,regsub()隻替換一次;
(2)ban(expression):
ban_url(regex):Bans所有其URL能夠由regex比對的緩存對象;
(3)purge:
從緩存中挑選出某對象以及其相關變種一并删除,這可以通過HTTP協定的PURGE方法完成;
(4)hash_data(str):
return():當某VCL域運作結束時将控制權傳回給Varnish,并訓示Varnish如何進行後續的動作;其可以傳回的指令包括:lookup、pass、pipe、hit_for_pass、fetch、deliver和hash等;但某特定域可能僅能傳回某些特定的指令
return(restart)重新運作整個VCL,即重新從vcl_recv開始進行處理;每一次重新開機都會增加req.restarts變量中的值,而max_restarts參數則用于限定最大重新開機次數。
4.常用變量
(1)在任何狀态引擎中均可
.host後端主機的主機名或者IP
.port後端主機的服務名或者端口号
(2)用于處理請求階段
client.ip用戶端ip
server.hostname緩存伺服器主機名
server.ip緩存伺服器ip
server.port緩存伺服器端口
req.request:請求方法
req.url:請求的URL
req.proto:請求的HTTP協定版本
req.backend:指定用于服務此次請求的後端主機
req.backend.healthy:後端主機的健康狀态
req.http.HEADER:調用request封包中http協定的指定的HEADER首部
req.can_gzip:用戶端是否能結束gzip壓縮格式響應内容
req.restarts:此請求被重新開機的次數
req.grace:寬限期響應
(3)varnish向backend主機發起請求前可用的變量
bereq.request:後端主機請求方法
bereq.url:後端主機請求路徑
bereq.proto:後端主機請求http協定
bereq.http.HEADER:後端主機HTTP首部
bereq.connect.timeout:等待後端建立連接配接的逾時時長
(4)backend主機的響應封包到達本主機(varnish)後,将其放置在cache中之前可用的變量
beresp.do_stream:流式響應(接收一個響應一個)
beresp.do_gzip:是否壓縮後存儲
beresp.do_gunzip:是否先解壓縮再存儲
beresp.http.HEADER:後端主機響應http首部
beresp.proto:後端主機響應http協定
beresp.status:後端主機響應狀态碼
beresp.response:響應的原因短語
beresp.ttl:響應對象剩餘的響應時長,機關為秒
beresp.backend.name指明此響應封包來源的後端主機的名稱
beresp.backend.ip指明此響應封包來源的後端主機的ip位址
beresp.backend.port指明此響應封包來源的後端主機的端口号
beresp.storage強制varnish存儲在指定的緩存後端
(5)緩存對象(從後端主機取出内容)存入cache之後可用變量
obj.proto:緩存對象響應時的協定
obj.status:緩存對象響應時的狀态碼
obj.response:緩存對象響應時的原因短語
obj.ttl:緩存對象響應時的生存時長
obj.hits:緩存對象響應時的命中次數
obj.http.HEADER:緩存對象響應時的的http首部
(6)在決定對請求的鍵做hash計算時可用變量
req.hash:指明将什麼鍵當成hash緩存的鍵
(7)在為用戶端準備響應封包時可用的變量
resp.proto響應的協定
resp.status響應的狀态碼
resp.response響應的響應原因短語
resp.http.HEADER響應的
變量的可用位置:
官方文檔:https://www.varnish-cache.org/docs/4.0/reference/vcl.html#varnish-configuration-language
5.使用案例概述
(1)變量指派:set name=value
執行個體:定義在vcl_deliver中,向響應給用戶端的封包添加一個自定義首部X-Cache;
if (obj.hits>0) {
set resp.http.X-Cache ="HIT";
} else {
set resp.http.X-Cahce ="MISS";
}
(2)支援虛拟主機:
if(req.http.host == "www.magedu.com"){
}
(3)強制對某資源的請求,不檢查緩存;
執行個體:對URL以/admin和/login結尾不做緩存:
if(req.url ~ "(?i)^/login" || req.url ~ "(?i)^/admin") {
return(pass);
(4)對特定類型的資源取消其私有的cookie辨別,并強行設定其可以varnish緩存的時長:
vcl_backend_response
if(beresp.http.cache-control !~ "s-maxage") {
if(bereq.url ~ "(?i)\.jpg$") {
setberesp.ttl = 3600s;
unsetberesp.http.Set-Cookie;
if(bereq.url ~ "(?i)\.css$") {
setberesp.ttl = 600s;
官方配置示例:https://www.varnish-cache.org/trac/wiki/VCLExamples
六、varnish後端主機健康監測和負載均衡
1.backend server的定義
backend name {
.attribute ="value";
.host
後端主機的IP;
.port
後端主機監聽的PORT;
.probe
對後端做健康狀态檢測;
.max_connections
并連接配接最大數量;
2.後端主機的健康狀态檢測方式
probe name {
.attribute= "value";
}
.url:
判定BE健康與否要請求的url;
.expected_response
期望響應狀态碼;預設為200;
執行個體一:
backendwebsrv1 {
.host = "172.16.100.68";
.port = "80";
.probe = {
.url = "/test1.html";
backendwebsrv2 {
.host = "172.16.100.69";
subvcl_recv {
if (req.url ~"(?i)\.(jpg|png|gif)$") {
set req.backend_hint = websrv1;
set req.backend_hint = websrv2;
}
執行個體二:
importdirectors;
subvcl_init {
new mycluster = directors.round_robin();
mycluster.add_backend(websrv1);
mycluster.add_backend(websrv2);
vcl_recv{
setreq.backend_hint = mycluster.backend();
負載均衡算法:fallback,random, round_robin, hash
七、實際案例
1.移除單個緩存對象
purge用于清理緩存中的某特定對象及其變種(variants),是以,在有着明确要修剪的緩存對象時可以使用此種方式。HTTP協定的PURGE方法可以實作purge功能,不過,其僅能用于vcl_hit和vcl_miss中,它會釋放記憶體工作并移除指定緩存對象的所有Vary:-變種,并等待下一個針對此内容的用戶端請求到達時重新整理此内容。另外,其一般要與return(restart)一起使用。下面是個在VCL中配置的示例。
aclpurgers {
"127.0.0.1";
"192.168.0.0"/24;
if(req.request == "PURGE") {
if(!client.ip ~ purgers) {
error405 "Method not allowed";
return(lookup);
subvcl_hit {
purge;
error200 "Purged";
subvcl_miss {
error404 "Not in cache";
subvcl_pass {
error502 "PURGE on a passed object";
用戶端在發起HTTP請求時,隻需要為所請求的URL使用PURGE方法即可,其指令使用方式如下:
#curl -I -X PURGE http://varniship/path/to/someurl
2.生産環境案例執行個體
aclpurge {
"localhost";
"127.0.0.1";
"10.1.0.0"/16;
"192.168.0.0"/16;
subvcl_hash {
hash_data(req.url);
return (hash);
set req.backend = shopweb;
# set req.grace = 4h;
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
return(lookup);
}
if (req.request == "REPURGE") {
ban("req.http.host == " +req.http.host + " && req.url ~ " + req.url);
error 200 "Ban OK";
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 != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS"&&
req.request != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird.*/
return (pipe);
if (req.request != "GET" &&req.request != "HEAD") {
/* We only deal with GET and HEAD bydefault */
return (pass);
if (req.http.Authorization) {
/* Not cacheable by default */
if ( req.url == "/Heartbeat.html" ){
if ( req.url == "/" ) {
if ( req.url == "/index.jsp" ) {
if (req.http.Cookie ~ "dper=") {
if (req.http.Cookie ~ "sqltrace="){
if (req.http.Cookie ~"errortrace=") {
# if ( req.request == "GET"&& req.url ~ "req.url ~ "^/shop/[0-9]+$" ) {
if ( req.url ~ "^/shop/[0-9]+$" ||req.url ~ "^/shop/[0-9]?.*" ) {
return (lookup);
if ( req.url ~"^/shop/(\d{1,})/editmember" || req.url ~"^/shop/(\d{1,})/map" || req.url ~"^/shop/(\d+)/dish-([^/]+)" ) {
return (pass);
# return (lookup);
subvcl_pipe {
return (pipe);
purge;
error 200 "Purged.";
return (deliver);
error 404 "Not in cache.";
# if (object needs ESI processing) {
# unset bereq.http.accept-encoding;
# }
return (fetch);
subvcl_fetch {
set beresp.ttl = 3600s;
set beresp.http.expires = beresp.ttl;
#set beresp.grace = 4h;
# set beresp.do_esi = true;
# set beresp.do_gzip = true;
if ( req.url ~ "^/shop/[0-9]+$" ||req.url ~ "^/shop/[0-9]?.*" ) {
set beresp.ttl = 4h;
set beresp.ttl = 24h;
if (beresp.status != 200){
return (hit_for_pass);
subvcl_deliver {
if (obj.hits > 0){
set resp.http.X-Cache = "HIT";
else {
set resp.http.X-Cache = "MISS";
set resp.http.X-Powered-By = "Cache on" + server.ip;
set resp.http.X-Age = resp.http.Age;
subvcl_error {
set obj.http.Content-Type = "text/html;charset=utf-8";
set obj.http.Retry-After = "5";
synthetic {""} + obj.status +" " + obj.response + {""};
return (ok);
subvcl_fini {