- 分布式系統(tǒng)架構(gòu):技術(shù)棧詳解與快速進(jìn)階
- 張程
- 99字
- 2020-08-13 13:45:39
5.3 Varnish配置
Varnish狀態(tài)引擎處理流程如圖5-2所示。

圖5-2 Varnish狀態(tài)引擎處理流程圖
對圖5-2所示的流程分析如下。
vcl_recv:用于接收并處理用戶請求,當(dāng)接收到一個完整的請求時,它會檢查并分析是否可以為這個請求服務(wù),判斷請求的數(shù)據(jù)并決定如何處理請求。vcl_recv可以選擇多個策略,如1.pipe、2.lookup、3.pass。它會將控制權(quán)傳遞給下游,如vcl_pipe、vcl_hash、vcl_pass。
- 1.1 vcl_pipe:不會緩存數(shù)據(jù),其會進(jìn)入pipe模式,由管道后端處理數(shù)據(jù),直到管道處理完畢后關(guān)閉。
- 2.1 vcl_hash:緩存數(shù)據(jù),通過hash處理機(jī)制,默認(rèn)URL可作為key,key的方式可自定義調(diào)整,同時可以根據(jù)客戶端是否區(qū)分壓縮數(shù)據(jù)而進(jìn)一步判斷是否存儲緩存。
- 2.2 vcl_hit:一個請求從緩存中命中需要的內(nèi)容。
- 2.3 vcl_miss:一個請求從緩存中未命中需要的內(nèi)容。
- 2.4/2.5 vcl_pass:對命中或未命中的數(shù)據(jù)提供數(shù)據(jù)處理功能。
- 2.8 vcl_fetch:從后端服務(wù)器獲得請求目標(biāo)數(shù)據(jù)。
- 2.9 deliver:從后端服務(wù)器獲得數(shù)據(jù)后,根據(jù)策略檢查是否需要緩存起來。
- 3.1/3.2 vcl_deliver:內(nèi)容返回給客戶端。
對圖5-2所示流程中涉及的函數(shù)介紹如下。
- pipe:將請求交給vcl_pipe函數(shù)。error code[reason]表示返回code給客戶端并放棄請求,code是錯誤標(biāo)示,例如200、405等,reason是錯誤原因。
- vcl_pipe:該函數(shù)在進(jìn)入pipe模式時被調(diào)用,用于將請求直接傳遞給后端主機(jī),在請求和返回內(nèi)容沒有改變的情況下,將不變的內(nèi)容返回給客戶端,直到這個鏈接關(guān)閉。
- vcl_pass:該函數(shù)在進(jìn)入pass模式時被調(diào)用,用于直接將請求發(fā)送給后端主機(jī),后端主機(jī)響應(yīng)后發(fā)送給客戶端,不進(jìn)行任何緩存,每次都返回最新內(nèi)容。
- vcl_hash:可緩存數(shù)據(jù),通過hash機(jī)制處理,默認(rèn)將URL作為key;也可以自定義,根據(jù)客戶端是否支持處理壓縮數(shù)據(jù)來區(qū)分緩存。
- lookup:在緩存中查找被請求的對象,并且根據(jù)查找的結(jié)果交給vcl_hit函數(shù)(命中)或vcl_miss函數(shù)(未命中)處理。
- vcl_hit:在執(zhí)行l(wèi)ookup后,如果在緩存中命中對象,該函數(shù)將會被自動調(diào)用。
- deliver:表示找到內(nèi)容并發(fā)送給客戶端,把控制權(quán)交給vcl_deliver函數(shù)。
- vcl_miss:在執(zhí)行l(wèi)ookup后,如果緩存中沒有命中對象,該函數(shù)會被調(diào)用,可用于判斷是否從后端請求內(nèi)容。
- fetch:表示從后端獲取內(nèi)容,并把控制權(quán)交給vcl_fetch函數(shù)。
- vcl_fetch:從后端主機(jī)更新緩存并獲取內(nèi)容后調(diào)用該函數(shù),接著判斷獲取的內(nèi)容是放入緩存還是直接給客戶端。
- vcl_deliver:將在緩存中找到的內(nèi)容發(fā)送給客戶端調(diào)用的方法。
下面介紹Varnish的配置文件(default.vcl),如代碼清單5-3所示。
代碼清單5-3 default.vcl配置文件
probe tz1{ .url="/demo/xxxx.index.html"; // 檢查后端健康頁面 .timeout=0.3s; // 過期時間 .window=8; // 檢查后端服務(wù)次數(shù) .threshod=3; // 檢查后端8次訪問,若成功3次則認(rèn)為服務(wù)是存活的 .initial=3; // Varnish啟動,確保多少個probe正常 .expected_response=200; // 期望expected code,默認(rèn)是200 .interval=6; // 定義probe多久檢查一次后端,默認(rèn)為5s } backend zachary{ .host="127.0.0.1"; .port="2222"; .connect_timeout=1s; .first_byte_timeout=5s; .between_byte.timeout=2s; .max_connections=1000; .probe=tz1; } backend resource{ .host="127.0.0.1"; .port="8099"; .connect_timeout=2s; // 定義等待連接后端的時間 .first_byte_timeout=5s; // 定義等待從backend傳輸過來的第一個字節(jié)的時間 .between_byte.timeout=2s; // 定義兩個字節(jié)的間隔時間 } director zachary random{ // 隨機(jī) .retries=5; // 查找可用后端次數(shù) { .backend=zachary; // 引用已存在的backend .weight=6; } { .backend=resource; // 引用已存在的backend .weight=2; // 類似Nginx權(quán)重 } { .backend={ // 定義新的backend } .weight=2; } } director zachary round-robin{ // 輪詢 { .backend=zachary; // 引用已存在的backend } { .backend=resource; // 引用已存在的backend } { .backend={ // 定義新的backend } } } #權(quán)限訪問控制列表 acl purgeallow { "127.0.0.1"; !"192.168.0.102" } sub vcl_recv{ if(!req.backend.healthy){ set req.grace=30m; // Varnish緩存時間+50分鐘返回給客戶端 }else{ set req.grace=5s; } if (req.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|t bz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") { unset req.http.cookie; return (hash); } if(req.request== "PURGE"){ (!client.ip ~ purgeallow){ error 405 "not allowed"; } return(lookup); } 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.http.Cache-Control ~ "(?i)no-cache") { if (!(req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) { return (purge); } } if(req.http.host ~"^(www.)?zachary.cn$"){ set req.backnd=zachary; } if(req.request== "GET" && req.url ~ "\.(jpg|png|gif|swf|flv|ico|jpeg)$"){ unset req.http.cookie; } if(req.request== "GET" && req.url ~ "(?i)\.jsp($|\?)"){ set req.backnd=resource; return pass(pass); } } sub vcl_fetch{ set beresp.grace=30m; // 后端服務(wù)器返回Varnish緩存時間+50分鐘 if(req.request== "GET" req.url ~ "\.(jpg|png|gif|swf|flv|ico|jpeg)$"){ set beresp.ttl=1d; } if(req.url ~ "^.*/zachary/demo/.*"){ set beresp.ttl=1d; return(deliver); } } sub vcl_hit{ std.log("url hit,your need to check it; it's url ="+req.url); if(req.request=='PURGE'){ set obj.ttl=0s; // 清除緩存 error 200 "Purged."; } return(fetch); } sub vcl_miss{ std.log("url miss,your need to check it; it's url ="+req.url); if(req.request=='PURGE'){ error 200 "Purged."; } return(fetch); }
對上述代碼中的重點(diǎn)流程介紹如下。
1)1個請求對應(yīng)1個backend,可配置連接后端服務(wù)。其中,connect_timeout表示連接后端超時時間,first_byte_timeout表示傳輸?shù)谝粋€字節(jié)的時間,between_byte.timeout表示第二個和第一個中間傳輸所用的時間,max_connections表示連接后端服務(wù)的最大限制數(shù)。
2)backend有多種配置策略,如隨機(jī)、循環(huán)、DNS等,可參考代碼清單5-3中的相關(guān)配置。
3)probe用于配置健康檢查。
4)acl用于設(shè)置權(quán)限列表,可配置相關(guān)IP。
當(dāng)多個客戶端請求同時訪問一個頁面時,Varnish只會發(fā)送一次請求到后端,其他請求會被掛起以等待返回結(jié)果,體驗(yàn)較差。當(dāng)服務(wù)器請求流量高時,比如在秒殺活動中、同時產(chǎn)生數(shù)千萬點(diǎn)擊率時等,用戶不可能掛起等待結(jié)果。
針對以上問題,Varnish提供了Grace模式來延長緩存失效時間,即上次過期數(shù)據(jù)結(jié)果在失效時間之后延期多長時間,具體時間需根據(jù)系統(tǒng)斟酌設(shè)置,當(dāng)后端服務(wù)器出現(xiàn)問題時,負(fù)載過高后,Varnish不訪問后端直接返回舊緩存數(shù)據(jù)到客戶端。
VCL返回策略:
- return(pass):不緩存,直接調(diào)用服務(wù)器。
- return(lookup):先從緩存獲取,緩存中沒有數(shù)據(jù)再從服務(wù)器獲取。
- return(pipe):當(dāng)前連接未關(guān)閉前,所有的請求都直接由服務(wù)器處理,Varnish不處理請求。
- return(deliver):請求目標(biāo)被緩存,然后返回客戶端。
5.4 Varnish核心指令
5.4.1 Varnish核心指令之backend
backend是用于定義后端服務(wù)器的子例程。其具體使用方法如代碼清單5-4所示。
代碼清單5-4 backend定義子例程
backend zachary{ .host="127.0.0.1"; // 指明后端主機(jī) .port="2222"; .connect_timeout=1s; .first_byte_timeout=5s; .between_byte.timeout=2s; .max_connections=1000; .probe=tz1; } backend resource{ .host="192.168.0.1"; // 指明后端主機(jī) .port="8099"; .connect_timeout=1s; .first_byte_timeout=5s; .between_byte.timeout=2s; }
注意
Varnish允許定義多個backend后端服務(wù)器。
- Web前端開發(fā)簡明教程(HTML+CSS+JavaScript+jQuery)
- 網(wǎng)絡(luò)化聯(lián)合仿真的時間同步
- TMS320C55x DSP原理及應(yīng)用(第3版)
- 網(wǎng)絡(luò)工程設(shè)計與系統(tǒng)集成(第2版)
- 新型網(wǎng)絡(luò)體系結(jié)構(gòu)
- ARM嵌入式體系結(jié)構(gòu)與接口技術(shù)(Cortex-A8版)
- 計算思維的結(jié)構(gòu)
- TMS 320 F28x源碼解讀
- 大學(xué)計算機(jī)基礎(chǔ)(第6版)
- 計算機(jī)體系結(jié)構(gòu)基礎(chǔ)(第3版)
- GPU高性能運(yùn)算之CUDA
- 兼容ARM9的軟核處理器設(shè)計:基于FPGA
- 大模型時代的基礎(chǔ)架構(gòu):大模型算力中心建設(shè)指南
- 嵌入式系統(tǒng)開發(fā)基礎(chǔ)與實(shí)踐教程
- 計算機(jī)組成原理(基于x86-64架構(gòu))