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

圖5-2 Varnish狀態(tài)引擎處理流程圖
對(duì)圖5-2所示的流程分析如下。
vcl_recv:用于接收并處理用戶請(qǐng)求,當(dāng)接收到一個(gè)完整的請(qǐng)求時(shí),它會(huì)檢查并分析是否可以為這個(gè)請(qǐng)求服務(wù),判斷請(qǐng)求的數(shù)據(jù)并決定如何處理請(qǐng)求。vcl_recv可以選擇多個(gè)策略,如1.pipe、2.lookup、3.pass。它會(huì)將控制權(quán)傳遞給下游,如vcl_pipe、vcl_hash、vcl_pass。
- 1.1 vcl_pipe:不會(huì)緩存數(shù)據(jù),其會(huì)進(jìn)入pipe模式,由管道后端處理數(shù)據(jù),直到管道處理完畢后關(guān)閉。
- 2.1 vcl_hash:緩存數(shù)據(jù),通過(guò)hash處理機(jī)制,默認(rèn)URL可作為key,key的方式可自定義調(diào)整,同時(shí)可以根據(jù)客戶端是否區(qū)分壓縮數(shù)據(jù)而進(jìn)一步判斷是否存儲(chǔ)緩存。
- 2.2 vcl_hit:一個(gè)請(qǐng)求從緩存中命中需要的內(nèi)容。
- 2.3 vcl_miss:一個(gè)請(qǐng)求從緩存中未命中需要的內(nèi)容。
- 2.4/2.5 vcl_pass:對(duì)命中或未命中的數(shù)據(jù)提供數(shù)據(jù)處理功能。
- 2.8 vcl_fetch:從后端服務(wù)器獲得請(qǐng)求目標(biāo)數(shù)據(jù)。
- 2.9 deliver:從后端服務(wù)器獲得數(shù)據(jù)后,根據(jù)策略檢查是否需要緩存起來(lái)。
- 3.1/3.2 vcl_deliver:內(nèi)容返回給客戶端。
對(duì)圖5-2所示流程中涉及的函數(shù)介紹如下。
- pipe:將請(qǐng)求交給vcl_pipe函數(shù)。error code[reason]表示返回code給客戶端并放棄請(qǐng)求,code是錯(cuò)誤標(biāo)示,例如200、405等,reason是錯(cuò)誤原因。
- vcl_pipe:該函數(shù)在進(jìn)入pipe模式時(shí)被調(diào)用,用于將請(qǐng)求直接傳遞給后端主機(jī),在請(qǐng)求和返回內(nèi)容沒(méi)有改變的情況下,將不變的內(nèi)容返回給客戶端,直到這個(gè)鏈接關(guān)閉。
- vcl_pass:該函數(shù)在進(jìn)入pass模式時(shí)被調(diào)用,用于直接將請(qǐng)求發(fā)送給后端主機(jī),后端主機(jī)響應(yīng)后發(fā)送給客戶端,不進(jìn)行任何緩存,每次都返回最新內(nèi)容。
- vcl_hash:可緩存數(shù)據(jù),通過(guò)hash機(jī)制處理,默認(rèn)將URL作為key;也可以自定義,根據(jù)客戶端是否支持處理壓縮數(shù)據(jù)來(lái)區(qū)分緩存。
- lookup:在緩存中查找被請(qǐng)求的對(duì)象,并且根據(jù)查找的結(jié)果交給vcl_hit函數(shù)(命中)或vcl_miss函數(shù)(未命中)處理。
- vcl_hit:在執(zhí)行l(wèi)ookup后,如果在緩存中命中對(duì)象,該函數(shù)將會(huì)被自動(dòng)調(diào)用。
- deliver:表示找到內(nèi)容并發(fā)送給客戶端,把控制權(quán)交給vcl_deliver函數(shù)。
- vcl_miss:在執(zhí)行l(wèi)ookup后,如果緩存中沒(méi)有命中對(duì)象,該函數(shù)會(huì)被調(diào)用,可用于判斷是否從后端請(qǐng)求內(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"; // 檢查后端健康頁(yè)面 .timeout=0.3s; // 過(guò)期時(shí)間 .window=8; // 檢查后端服務(wù)次數(shù) .threshod=3; // 檢查后端8次訪問(wèn),若成功3次則認(rèn)為服務(wù)是存活的 .initial=3; // Varnish啟動(dòng),確保多少個(gè)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; // 定義等待連接后端的時(shí)間 .first_byte_timeout=5s; // 定義等待從backend傳輸過(guò)來(lái)的第一個(gè)字節(jié)的時(shí)間 .between_byte.timeout=2s; // 定義兩個(gè)字節(jié)的間隔時(shí)間 } director zachary random{ // 隨機(jī) .retries=5; // 查找可用后端次數(shù) { .backend=zachary; // 引用已存在的backend .weight=6; } { .backend=resource; // 引用已存在的backend .weight=2; // 類(lèi)似Nginx權(quán)重 } { .backend={ // 定義新的backend } .weight=2; } } director zachary round-robin{ // 輪詢 { .backend=zachary; // 引用已存在的backend } { .backend=resource; // 引用已存在的backend } { .backend={ // 定義新的backend } } } #權(quán)限訪問(wèn)控制列表 acl purgeallow { "127.0.0.1"; !"192.168.0.102" } sub vcl_recv{ if(!req.backend.healthy){ set req.grace=30m; // Varnish緩存時(shí)間+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緩存時(shí)間+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); }
對(duì)上述代碼中的重點(diǎn)流程介紹如下。
1)1個(gè)請(qǐng)求對(duì)應(yīng)1個(gè)backend,可配置連接后端服務(wù)。其中,connect_timeout表示連接后端超時(shí)時(shí)間,first_byte_timeout表示傳輸?shù)谝粋€(gè)字節(jié)的時(shí)間,between_byte.timeout表示第二個(gè)和第一個(gè)中間傳輸所用的時(shí)間,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)多個(gè)客戶端請(qǐng)求同時(shí)訪問(wèn)一個(gè)頁(yè)面時(shí),Varnish只會(huì)發(fā)送一次請(qǐng)求到后端,其他請(qǐng)求會(huì)被掛起以等待返回結(jié)果,體驗(yàn)較差。當(dāng)服務(wù)器請(qǐng)求流量高時(shí),比如在秒殺活動(dòng)中、同時(shí)產(chǎn)生數(shù)千萬(wàn)點(diǎn)擊率時(shí)等,用戶不可能掛起等待結(jié)果。
針對(duì)以上問(wèn)題,Varnish提供了Grace模式來(lái)延長(zhǎng)緩存失效時(shí)間,即上次過(guò)期數(shù)據(jù)結(jié)果在失效時(shí)間之后延期多長(zhǎng)時(shí)間,具體時(shí)間需根據(jù)系統(tǒng)斟酌設(shè)置,當(dāng)后端服務(wù)器出現(xiàn)問(wèn)題時(shí),負(fù)載過(guò)高后,Varnish不訪問(wèn)后端直接返回舊緩存數(shù)據(jù)到客戶端。
VCL返回策略:
- return(pass):不緩存,直接調(diào)用服務(wù)器。
- return(lookup):先從緩存獲取,緩存中沒(méi)有數(shù)據(jù)再?gòu)姆?wù)器獲取。
- return(pipe):當(dāng)前連接未關(guān)閉前,所有的請(qǐng)求都直接由服務(wù)器處理,Varnish不處理請(qǐng)求。
- return(deliver):請(qǐng)求目標(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允許定義多個(gè)backend后端服務(wù)器。
- Web前端開(kāi)發(fā)簡(jiǎn)明教程(HTML+CSS+JavaScript+jQuery)
- 網(wǎng)絡(luò)化聯(lián)合仿真的時(shí)間同步
- 網(wǎng)絡(luò)工程設(shè)計(jì)與系統(tǒng)集成(第2版)
- TMS320C55x DSP原理及應(yīng)用(第3版)
- ARM嵌入式體系結(jié)構(gòu)與接口技術(shù)(Cortex-A8版)
- 新型網(wǎng)絡(luò)體系結(jié)構(gòu)
- 計(jì)算思維的結(jié)構(gòu)
- TMS 320 F28x源碼解讀
- 大學(xué)計(jì)算機(jī)基礎(chǔ)(第6版)
- GPU高性能運(yùn)算之CUDA
- 計(jì)算機(jī)體系結(jié)構(gòu)基礎(chǔ)(第3版)
- 兼容ARM9的軟核處理器設(shè)計(jì):基于FPGA
- 大模型時(shí)代的基礎(chǔ)架構(gòu):大模型算力中心建設(shè)指南
- 嵌入式系統(tǒng)開(kāi)發(fā)基礎(chǔ)與實(shí)踐教程
- 計(jì)算機(jī)組成原理(基于x86-64架構(gòu))