Varnish部署
上緩存服務(wù)器的目的:
1、減少clint對(duì)后端服務(wù)器的訪問(wèn)壓力。
2、在靜態(tài)資源較多的情況下,服務(wù)端可以快速對(duì)clint的訪問(wèn)做出相應(yīng)。
緩存服務(wù)器目前比較有名氣,市面上緩存代理服務(wù)器使用比較多的Varnish/squid。
squid的主要是緩存大文件。
Varnish主要緩存靜態(tài)資源,如圖片。
Varnish版本的區(qū)別:
新版本Varnish4,client/backend分離,新的vanishlog查詢語(yǔ)言,安全方面據(jù)說(shuō)有提升。
首先是必須定義版本號(hào): vcl 4.0。VMOD’s更獨(dú)立化,官方推薦是加載Standard VMOD’s(std)。
另外director已變?yōu)閂MOD,如需使用,需要import directors。
vcl_fetch函數(shù)被vcl_backend_response和vcl_backend_fetch代替,且req.*不再適用vcl_backend_response,只能使用bereq.*。
至于vcl_backend_fetch貌似沒(méi)哪個(gè)doc見(jiàn)到詳細(xì)用法。
error變更為return(synth(http_code,message)),req.backend成了req.backend_hint,req.request變更為req.method,obj為只讀對(duì)象了。
vcl_synth采用resp.*,而非原來(lái)的obj.*。
vcl_error變更為vcl_backend_error,必須使用beresp.*,而不是obj.*。
關(guān)鍵字"purge;"命令,已被去除。在vcl_recv使用return(purge)。
hit_for_pass通過(guò)set beresp.uncacheable = true;來(lái)指定。
vcl_recv必須將lookup變更返回hash,vcl_hash必須將hash變更返回lookup,vcl_pass必須將pass變更返回fetch。
req.backend.healty被std.healthy(req.backend)代替,但是設(shè)置不了grace,雞肋,被拋棄了,現(xiàn)在僅能做的就是keepalive的作用了。
req、bereq,resp、beresp之間不同,可被使用的位置不同。
server.port、client.port分別變更為std.port(server.ip)、std.port(client.ip),跟上面healthy一樣,需要import std。
session_linger變更為timeout_linger,sess_timeout變更為timeout_idle,sess_workspace被拋棄了。
remove被完全棄用了,不過(guò)我一直用unset的說(shuō)。
return(restart)變更為return(retry),vcl_backend_fetch會(huì)被使用到。
自定義sub函數(shù)不能以vcl_開(kāi)頭,調(diào)用方式call udf。
部署架構(gòu):單節(jié)點(diǎn)/雙節(jié)點(diǎn)
1、如果你們的服務(wù)在云節(jié)點(diǎn)部署那久簡(jiǎn)單了,流行的云平臺(tái)都有負(fù)載均衡器(HA/LB)等等,部署2臺(tái)Varnish 掛載后端nginx 就完事了。
2、如果你們自建機(jī)房,Varnish的前端代理可以選擇(Nginx/HA),這2套開(kāi)源軟件都比較流行,做代理性能也不錯(cuò)。
下面是大致的Varnish邏輯圖:
第一種全部單節(jié)點(diǎn):
第二種Varnish雙節(jié)點(diǎn),Nginx單節(jié)點(diǎn):
第三種雙節(jié)點(diǎn):
?Varnish的安裝上篇已經(jīng)寫(xiě)過(guò),請(qǐng)參考之前的博客;
Varnish配置參數(shù):
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | cat?/etc/sysconfig/varnish #?Maximum?number?of?open?files?(for?ulimit?-n)??#打開(kāi)文件的最大個(gè)數(shù),limit可以修改 NFILES=131072 #?Default?log?size?is?82MB?+?header???#日志文件大小82M MEMLOCK=82000 #?Maximum?number?of?threads?(for?ulimit?-u)??#最大線程數(shù),使用unlimited變量 NPROCS="unlimited" #?Maximum?size?of?corefile?(for?ulimit?-c).?Default?in?Fedora?is?0??#打開(kāi)的最大核心文件數(shù),Fedora默認(rèn)是0?? #?DAEMON_COREFILE_LIMIT="unlimited" #?Set?this?to?1?to?make?init?script?reload?try?to?switch?vcl?without?restart. #?To?make?this?work,?you?need?to?set?the?following?variables #?explicit:?VARNISH_VCL_CONF,?VARNISH_ADMIN_LISTEN_ADDRESS, #?VARNISH_ADMIN_LISTEN_PORT,?VARNISH_SECRET_FILE,?or?in?short, #?use?Alternative?3,?Advanced?configuration,?below RELOAD_VCL=1????#如果配置為1,重新load?varnish配置文件vcl,varnish服務(wù)器不會(huì)重啟,可能是熱加載吧,不清楚使用默認(rèn) #?#?Main?configuration?file.?You?probably?want?to?change?it?:) VARNISH_VCL_CONF=/etc/varnish/default.vcl??????#Varnish默認(rèn)加載的配置文件 #?VARNISH_LISTEN_ADDRESS=??#Varnish監(jiān)控的端口,改為80,修改的 VARNISH_LISTEN_PORT=80 #?#?Telnet?admin?interface?listen?address?and?port???#Varnish的管理端口 VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 VARNISH_ADMIN_LISTEN_PORT=6082 #?#?Shared?secret?file?for?admin?interface VARNISH_SECRET_FILE=/etc/varnish/secret????#Varnish的secret文件,默認(rèn) #?#?The?minimum?number?of?worker?threads?to?start???#Varnish最小線程數(shù) VARNISH_MIN_THREADS=50 #?#?The?Maximum?number?of?worker?threads?to?start VARNISH_MAX_THREADS=4000????????#Varnish最大線程數(shù),默認(rèn)1000,不超過(guò)5000?應(yīng)該沒(méi)問(wèn)題 #?#?Idle?timeout?for?worker?threads VARNISH_THREAD_TIMEOUT=120??????#超時(shí) #?#?Cache?file?size:?in?bytes,?optionally?using?k?/?M?/?G?/?T?suffix, #?#?or?in?percentage?of?available?disk?space?using?the?%?suffix. VARNISH_STORAGE_SIZE=512M?????#Varnish使用的空間大小默認(rèn) #?#?Backend?storage?specification VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}"???#存儲(chǔ)空間使用內(nèi)存,file是磁盤(pán) #?#?Default?TTL?used?when?the?backend?does?not?specify?one VARNISH_TTL=120???#Varnish緩存時(shí)間120s |
Varnish的配置文件,這塊使用的版本4.0的,其他版本還是有區(qū)別的,Varnish官網(wǎng)到5版本了。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | [root@www?varnish]#?cat?default.vcl? # #?This?is?an?example?VCL?file?for?Varnish. # #?It?does?not?do?anything?by?default,?delegating?control?to?the #?builtin?VCL.?The?builtin?VCL?is?called?when?there?is?no?explicit #?return?statement. # #?See?the?VCL?chapters?in?the?Users?Guide?at?https://www.varnish-cache.org/docs/ #?and?http://varnish-cache.org/trac/wiki/VCLExamples?for?more?examples. #?Marker?to?tell?the?VCL?compiler?that?this?VCL?has?been?adapted?to?the #?new?4.0?format. vcl?4.0; #導(dǎo)入directors模塊,基于負(fù)載均衡調(diào)度,后端多個(gè)主機(jī)可以使用輪詢 import?directors; #?Default?backend?definition.?Set?this?to?point?to?your?content?server. #這塊以單節(jié)點(diǎn)演示 backend?web1?{ ????.host?=?"172.16.2.27"; ????.port?=?"80"; } #注意:用戶請(qǐng)求成功后,對(duì)請(qǐng)求的數(shù)據(jù)做處理,varnish4走緩存使用return?(hash);?varnish3走緩存使用?return(lookup);還是有區(qū)別的。 sub?vcl_recv?{???? ???if?(req.http.host?~?"(www.)?laiwojia.la")?{??#如果請(qǐng)求的是www域名就走web1 ????set?req.backend_hint?=?web1; } #return(hash);#否則就走h(yuǎn)ash;這條最好寫(xiě)到vcl_recv配置末尾,這是if判斷,除了www走web1,其余url都是hash,后續(xù)的測(cè)試pass的你會(huì)發(fā)現(xiàn)全是命中,注釋掉此行后才會(huì)pass ????if?(req.url?~?"(?i)^/(login|admin)")?{#登錄pass ????return(pass); } ????if?(req.url?~?"(?i)\.php$")?{#訪問(wèn)url是php結(jié)尾走web1 ????????set?req.backend_hint?=?web1; ????} ????if?(req.url?~?"(?i)\.(jpg|jpeg|png|gif|css|js)$")?{#圖片走web1 ????set?req.backend_hint?=?web1; } ####注意:varnish4.*版本使用時(shí)req.method;varnish3.*的版本使用req.request,這點(diǎn)要注意 if?(req.method?!="GET"?&&?req.method?!=?"HEAD"?&&?req.method?!=?"PUT"?&&?req.method?!=?"POST"?&&?req.method?!=?"TRACE"?&&?req.method?!=?"OPTIONS"?&&?req.method?!=?"PATCH"?&&??req.method?!=?"DELETE")?{ ????return?(pipe); } if?(req.http.Upgrade?~?"(?i)websocket")?{ ????return?(pipe); ??} if?(req.method?!=?"GET"?&&?req.method?!=?"HEAD")?{ ????return?(pass); ??} ??#下面這段是我看到別人github上的資源,發(fā)現(xiàn)比較全摘錄的,壓縮、圖片、視頻流、文檔等,訪問(wèn)這些資源不保存cookie信息; if?(req.url?~?"^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$")?{ ????unset?req.http.Cookie; ????return?(hash); ??} ??#這段其實(shí)和上面的有些重復(fù),二選一或者全保留也沒(méi)錯(cuò), if?(req.http.Authorization?||?req.http.Cookie)?{ ????return?(pass); } if?(req.url?~?"test.html")?{?#這是上面測(cè)試的,如果請(qǐng)求的是test.html?就pass,之前return?(hash),寫(xiě)在上面,怎么訪問(wèn)都是hit,查看配置文件 ????return?(pass); } ????return?(hash);#否則就走緩存,3.0還是2.0貌似都是return?(lookup),4.0?是return?(hash),我嘗試些lookup?運(yùn)行發(fā)現(xiàn)報(bào)錯(cuò) } #對(duì)于特定類型的資源,例如公開(kāi)的圖片等,取消其私有標(biāo)識(shí),并強(qiáng)行設(shè)定其可以由varnish緩存的時(shí)長(zhǎng) 下面是服務(wù)器端對(duì)緩存服務(wù)器的響應(yīng) sub?vcl_backend_response?{ ????if?(beresp.http.cache-control?!~?"s-maxage")?{ ????????if?(bereq.url?~?"(?i)\.(jpg|jpeg|png|gif|css|js)$")?{ ????????????unset?beresp.http.Set-Cookie; ????????????set?beresp.ttl?=?3600s; ????????} } ?????if?(bereq.http.host?==?"(www.)?laiwojia.la")?{ ????????if?(bereq.url?~?"(?i)/api/product/hotlist" ???????????||bereq.url?~?"(?i)/api/dolphin/list" ???????????||bereq.url?~?"(?i)/api/product/baseInfo" ???????????||bereq.url?~?"(?i)/api/product/desc" ???????????||bereq.url?~?"(?i)/api/search/brandRecommendProduct"??? ???????????||bereq.url?~?"(?i)/cms/view/h5/headlinesList"??? ???????????||bereq.url?~?"(?i)/cms/view/h5/category"??????? ???????????||bereq.url?~?"(?i)/cms/view/h5/article"??????? ???????????||bereq.url?~?"(?i)/cms/view/h5/\w+\.html"????? ???????????||bereq.url?~?"(?i)/api/product/distributions") ????????{ ?????????set?beresp.ttl?=?300s;??//緩存時(shí)間改為5分鐘 ????????} ????????elseif?(bereq.url?~?"(?i)/api/search/searchList\?sortType=volume4sale_desc\&companyId=10\&keyword=\*\*\*\*\*\&pageSize=10"?) ????????{ ??????????set?beresp.ttl?=?60s;??//設(shè)置為1分鐘 ????????} ????????elseif?(bereq.url?~?"(?i)/cms/view/.*/templateJS\.json"? ??????????????||bereq.url?~?"(?i)\.html") ????????{ ??????????set?beresp.ttl?=?600s;??//設(shè)置為10分鐘 ????????} ????????elseif?(bereq.url?~?"(?i)/libs/") ????????{ ???????????set?beresp.ttl?=?1800s; ????????} ????????????set?beresp.grace?=?2m; } } sub?vcl_pipe?{ if?(req.http.upgrade)?{ ????set?bereq.http.upgrade?=?req.http.upgrade; ??} ????return?(pipe); } sub?vcl_pass?{ #return?(pass); } sub?vcl_hash?{ ????hash_data(req.url); ????if?(req.http.host)?{ ????????hash_data(req.http.host); }?else?{ ?????????hash_data(server.ip); } if?(req.http.Cookie)?{ ????hash_data(req.http.Cookie); ??} } sub?vcl_hit?{ ????if?(obj.ttl?>=?0s)?{ ????return?(deliver); } } sub?vcl_miss?{ ????return?(fetch); } #結(jié)果投遞,下面二選一都行 #響應(yīng) #sub?vcl_deliver?{ #????if?(obj.hits?>?0)?{ #???????set?resp.http.X-Cache?=?"Hit"+server.ip;?//服務(wù)器響應(yīng)返回"HIT"?+?Varnish?server?ip #?????}?else?{ #???????set?resp.http.X-Cache?=?"Miss";?//返回未命中 #?????} #} sub?vcl_deliver?{ ????set?resp.http.X-Age?=?resp.http.Age;??#響應(yīng)返回Age, ????unset?resp.http.X-Age; ????if?(obj.hits?>?0)?{ ????????set?resp.http.X-Cache?=?"HIT"+server.hostname;#服務(wù)器響應(yīng)只返回命中或者未命中; ????}?else?{ ????????set?resp.http.X-Cache?=?"MISS"; ????} } |
需要配置文件參考的可以直接博客回復(fù);
Varnish的常用命令:
重新載入配置文件:varnish_reload_vcl
查看Varnish的日志常被緩存的資源:varnishlog
另一種查看日志的姿勢(shì):varnishncsa
Varnish的管理端口命令:varnishadm
查看varnish命中比率:varnishstat
圖標(biāo)查看varnish命中:varnishhist
配置測(cè)試:
第一種測(cè)試:直接略過(guò)Varnish,直接訪問(wèn)nginx測(cè)試:
通過(guò)linux自帶命令curl訪問(wèn)
查看nginx日志:
第二種訪問(wèn)域名,域名解析在Varnish這臺(tái)主機(jī):
curl域名測(cè)試:
查看結(jié)果:
第三種:通過(guò)web 瀏覽器訪問(wèn),查看命中:
第四種測(cè)試:
改變index.html文件內(nèi)容,測(cè)試結(jié)果:第一次都不會(huì)命中,第二次/第三次全部命中。
配置Varnish,只要是test.html文件就pass,測(cè)試結(jié)果:
以下是return (pass)和return (pipe)的區(qū)別,摘錄別人的博客:
調(diào)用 pass 函數(shù),從后端服務(wù)器調(diào)用數(shù)據(jù)。?
?
調(diào)用 pipe 函數(shù),建立客戶端和后端服務(wù)器之間的直接連接,從后端服務(wù)器調(diào)用數(shù)據(jù)。?
?
調(diào)用hash函數(shù),從緩存中查找應(yīng)答數(shù)據(jù)并返回,如果查找不到,則調(diào)用pass函數(shù)從后端服務(wù)器
調(diào)用數(shù)據(jù) 。?
http 建立連接的過(guò)程 ?
?
http 請(qǐng)求的類型:get post head?
先說(shuō)http建立連接的過(guò)程
?
當(dāng)瀏覽器想要獲得一個(gè)網(wǎng)頁(yè)內(nèi)容時(shí),如在瀏覽器輸入www.google.com。?
?
這時(shí)瀏覽器開(kāi)始跟服務(wù)器建立連接,先執(zhí)行三次握手,確認(rèn)建立連接。?
?
之后瀏覽器會(huì)發(fā)送請(qǐng)求,一個(gè)網(wǎng)頁(yè)包含多個(gè)內(nèi)容,如圖片,正文,html代碼,css代碼,js代碼。
如果在html 1.0版本中,請(qǐng)求一個(gè)文件是需要建立一次連接的,多個(gè)請(qǐng)求多個(gè)連接。開(kāi)銷(xiāo)是很大的。
而在HTML 1.1中,具有了長(zhǎng)連接的特性,允許在keep-live 時(shí)間內(nèi)保持連接,在這段時(shí)間內(nèi)無(wú)須
再建立連接就可以發(fā)送多個(gè)請(qǐng)求。?
?
請(qǐng)求完成 或 keep-live時(shí)間到限,連接斷開(kāi)。?
HTTP 請(qǐng)求的類型:
?
HTTP 請(qǐng)求的類型有幾種,下面是主要的幾種:?
? GET : 請(qǐng)求指定的頁(yè)面信息,并返回實(shí)體主體。?
HEAD: 只請(qǐng)求頁(yè)面的首部。?
POST: 請(qǐng)求服務(wù)器接受所指定的文檔作為對(duì)所標(biāo)識(shí)的URI的新的從屬實(shí)體。?
說(shuō)白了,請(qǐng)求一個(gè)靜態(tài)的HTML頁(yè)面就是用get類型,而如果你在新浪微博上發(fā)一條微博,其實(shí)就是post 類型。
總結(jié)來(lái)說(shuō),get是請(qǐng)求相關(guān)URI并接受服務(wù)器的返回?cái)?shù)據(jù)。為了接收數(shù)據(jù)。
post是發(fā)送數(shù)據(jù)給服務(wù)器,服務(wù)器需要對(duì)這些數(shù)據(jù)做相應(yīng)的處理。為了發(fā)送數(shù)據(jù)。
?
以上都明白的話,就可以解答這三個(gè)問(wèn)題了:
?
pass和pipe都從后端服務(wù)器取數(shù)據(jù),它們之間有什么不同呢? ?
??
什么情況下用pass,什么情況下用pipe呢? ?
??
什么樣的數(shù)據(jù)會(huì)被緩存在varnish中呢? ?
?
問(wèn):pass和pipe都從后端服務(wù)器取數(shù)據(jù),它們之間有什么不同呢? ?
答:當(dāng)vcl_recv調(diào)用 pass 函數(shù)時(shí),pass將當(dāng)前請(qǐng)求直接轉(zhuǎn)發(fā)到后端服務(wù)器。而后續(xù)的請(qǐng)求仍然
通過(guò)varnish處理。?
例如,建立了HTTP連接之后,客戶端順序請(qǐng)求 a.css 、a.png兩個(gè)文件,“當(dāng)前請(qǐng)求”指的是第一個(gè)
請(qǐng)求,即a.css,a.css被直接轉(zhuǎn)發(fā)到后端服務(wù)器,不被緩存。而后續(xù)的a.png則再由varnish來(lái)做
處理,varnish會(huì)判斷a.png 如何處理。?
總結(jié):一個(gè)連接中除了當(dāng)前請(qǐng)求,其它請(qǐng)求仍然按照正常情況由varnish處理。?
?
而pipe模式則不一樣,當(dāng)vcl_recv判斷 需要調(diào)用 pipe 函數(shù)時(shí),varnish會(huì)在客戶端和服務(wù)器之
間建立一條直接的連接 ,之后客戶端的所有請(qǐng)求都直接發(fā)送給服務(wù)器,繞過(guò)varnish,不再由varnish
檢查請(qǐng)求,直到連接斷開(kāi)。?
?
什么情況下用pass,什么情況下用pipe呢? ?
答:pass 通常只處理靜態(tài)頁(yè)面。即只在GET 和 HEAD 類型的請(qǐng)求中時(shí)才適合調(diào)用pass函數(shù)。
另外,需要注意的一點(diǎn)是,pass模式不能處理POST請(qǐng)求,為什么呢?因?yàn)镻OST請(qǐng)求一般是發(fā)送
數(shù)據(jù)給服務(wù)器,需要服務(wù)器接收數(shù)據(jù),并處理數(shù)據(jù),反饋數(shù)據(jù) 。是動(dòng)態(tài)的,不作緩存。?
示例代碼如下:?
if (req.request !="GET" && req.request != "HEAD")?
{ ? ? ? ? ? ? ??
return (pipe); ? ? ??
} ? ? ??
那什么情況下用pipe?由以上陳述可以知,類型是POST時(shí)用pipe,但是也許還不太清晰。舉個(gè)例子,
當(dāng)客戶端在請(qǐng)求一個(gè)視頻文件時(shí),或者一個(gè)大的文檔,如.zip .tar 文件,就需要用pipe模式,
這些大的文件是不被緩存在varnish中的。?
?
什么樣的數(shù)據(jù)會(huì)被緩存在varnish中呢? ??
答:varnish只緩存靜態(tài)數(shù)據(jù)。在網(wǎng)上搜到的varnish緩存策略,可以解答這個(gè)問(wèn)題:?
varnish緩存策略?
?
缺省是根椐后端返回的http狀態(tài)碼決定是否緩存。可以緩存的狀態(tài)碼如下:?
200 ? ?
203 ? ?
300 ? ?
301 ? ?
302 ? ?
410 ? ?
404?
這位大師的博客鏈接:http://yeelone.blog.51cto.com/1476571/772369/
總結(jié)
- 上一篇: jQuery知识简介
- 下一篇: 利用nginx和mongrel、unic