Varnish部署
上緩存服務器的目的:
1、減少clint對后端服務器的訪問壓力。
2、在靜態資源較多的情況下,服務端可以快速對clint的訪問做出相應。
緩存服務器目前比較有名氣,市面上緩存代理服務器使用比較多的Varnish/squid。
squid的主要是緩存大文件。
Varnish主要緩存靜態資源,如圖片。
Varnish版本的區別:
新版本Varnish4,client/backend分離,新的vanishlog查詢語言,安全方面據說有提升。
首先是必須定義版本號: vcl 4.0。VMOD’s更獨立化,官方推薦是加載Standard VMOD’s(std)。
另外director已變為VMOD,如需使用,需要import directors。
vcl_fetch函數被vcl_backend_response和vcl_backend_fetch代替,且req.*不再適用vcl_backend_response,只能使用bereq.*。
至于vcl_backend_fetch貌似沒哪個doc見到詳細用法。
error變更為return(synth(http_code,message)),req.backend成了req.backend_hint,req.request變更為req.method,obj為只讀對象了。
vcl_synth采用resp.*,而非原來的obj.*。
vcl_error變更為vcl_backend_error,必須使用beresp.*,而不是obj.*。
關鍵字"purge;"命令,已被去除。在vcl_recv使用return(purge)。
hit_for_pass通過set beresp.uncacheable = true;來指定。
vcl_recv必須將lookup變更返回hash,vcl_hash必須將hash變更返回lookup,vcl_pass必須將pass變更返回fetch。
req.backend.healty被std.healthy(req.backend)代替,但是設置不了grace,雞肋,被拋棄了,現在僅能做的就是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被完全棄用了,不過我一直用unset的說。
return(restart)變更為return(retry),vcl_backend_fetch會被使用到。
自定義sub函數不能以vcl_開頭,調用方式call udf。
部署架構:單節點/雙節點
1、如果你們的服務在云節點部署那久簡單了,流行的云平臺都有負載均衡器(HA/LB)等等,部署2臺Varnish 掛載后端nginx 就完事了。
2、如果你們自建機房,Varnish的前端代理可以選擇(Nginx/HA),這2套開源軟件都比較流行,做代理性能也不錯。
下面是大致的Varnish邏輯圖:
第一種全部單節點:
第二種Varnish雙節點,Nginx單節點:
第三種雙節點:
?Varnish的安裝上篇已經寫過,請參考之前的博客;
Varnish配置參數:
| 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)??#打開文件的最大個數,limit可以修改 NFILES=131072 #?Default?log?size?is?82MB?+?header???#日志文件大小82M MEMLOCK=82000 #?Maximum?number?of?threads?(for?ulimit?-u)??#最大線程數,使用unlimited變量 NPROCS="unlimited" #?Maximum?size?of?corefile?(for?ulimit?-c).?Default?in?Fedora?is?0??#打開的最大核心文件數,Fedora默認是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服務器不會重啟,可能是熱加載吧,不清楚使用默認 #?#?Main?configuration?file.?You?probably?want?to?change?it?:) VARNISH_VCL_CONF=/etc/varnish/default.vcl??????#Varnish默認加載的配置文件 #?VARNISH_LISTEN_ADDRESS=??#Varnish監控的端口,改為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文件,默認 #?#?The?minimum?number?of?worker?threads?to?start???#Varnish最小線程數 VARNISH_MIN_THREADS=50 #?#?The?Maximum?number?of?worker?threads?to?start VARNISH_MAX_THREADS=4000????????#Varnish最大線程數,默認1000,不超過5000?應該沒問題 #?#?Idle?timeout?for?worker?threads VARNISH_THREAD_TIMEOUT=120??????#超時 #?#?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使用的空間大小默認 #?#?Backend?storage?specification VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}"???#存儲空間使用內存,file是磁盤 #?#?Default?TTL?used?when?the?backend?does?not?specify?one VARNISH_TTL=120???#Varnish緩存時間120s |
Varnish的配置文件,這塊使用的版本4.0的,其他版本還是有區別的,Varnish官網到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; #導入directors模塊,基于負載均衡調度,后端多個主機可以使用輪詢 import?directors; #?Default?backend?definition.?Set?this?to?point?to?your?content?server. #這塊以單節點演示 backend?web1?{ ????.host?=?"172.16.2.27"; ????.port?=?"80"; } #注意:用戶請求成功后,對請求的數據做處理,varnish4走緩存使用return?(hash);?varnish3走緩存使用?return(lookup);還是有區別的。 sub?vcl_recv?{???? ???if?(req.http.host?~?"(www.)?laiwojia.la")?{??#如果請求的是www域名就走web1 ????set?req.backend_hint?=?web1; } #return(hash);#否則就走hash;這條最好寫到vcl_recv配置末尾,這是if判斷,除了www走web1,其余url都是hash,后續的測試pass的你會發現全是命中,注釋掉此行后才會pass ????if?(req.url?~?"(?i)^/(login|admin)")?{#登錄pass ????return(pass); } ????if?(req.url?~?"(?i)\.php$")?{#訪問url是php結尾走web1 ????????set?req.backend_hint?=?web1; ????} ????if?(req.url?~?"(?i)\.(jpg|jpeg|png|gif|css|js)$")?{#圖片走web1 ????set?req.backend_hint?=?web1; } ####注意:varnish4.*版本使用時req.method;varnish3.*的版本使用req.request,這點要注意 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上的資源,發現比較全摘錄的,壓縮、圖片、視頻流、文檔等,訪問這些資源不保存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); ??} ??#這段其實和上面的有些重復,二選一或者全保留也沒錯, if?(req.http.Authorization?||?req.http.Cookie)?{ ????return?(pass); } if?(req.url?~?"test.html")?{?#這是上面測試的,如果請求的是test.html?就pass,之前return?(hash),寫在上面,怎么訪問都是hit,查看配置文件 ????return?(pass); } ????return?(hash);#否則就走緩存,3.0還是2.0貌似都是return?(lookup),4.0?是return?(hash),我嘗試些lookup?運行發現報錯 } #對于特定類型的資源,例如公開的圖片等,取消其私有標識,并強行設定其可以由varnish緩存的時長 下面是服務器端對緩存服務器的響應 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;??//緩存時間改為5分鐘 ????????} ????????elseif?(bereq.url?~?"(?i)/api/search/searchList\?sortType=volume4sale_desc\&companyId=10\&keyword=\*\*\*\*\*\&pageSize=10"?) ????????{ ??????????set?beresp.ttl?=?60s;??//設置為1分鐘 ????????} ????????elseif?(bereq.url?~?"(?i)/cms/view/.*/templateJS\.json"? ??????????????||bereq.url?~?"(?i)\.html") ????????{ ??????????set?beresp.ttl?=?600s;??//設置為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); } #結果投遞,下面二選一都行 #響應 #sub?vcl_deliver?{ #????if?(obj.hits?>?0)?{ #???????set?resp.http.X-Cache?=?"Hit"+server.ip;?//服務器響應返回"HIT"?+?Varnish?server?ip #?????}?else?{ #???????set?resp.http.X-Cache?=?"Miss";?//返回未命中 #?????} #} sub?vcl_deliver?{ ????set?resp.http.X-Age?=?resp.http.Age;??#響應返回Age, ????unset?resp.http.X-Age; ????if?(obj.hits?>?0)?{ ????????set?resp.http.X-Cache?=?"HIT"+server.hostname;#服務器響應只返回命中或者未命中; ????}?else?{ ????????set?resp.http.X-Cache?=?"MISS"; ????} } |
需要配置文件參考的可以直接博客回復;
Varnish的常用命令:
重新載入配置文件:varnish_reload_vcl
查看Varnish的日志常被緩存的資源:varnishlog
另一種查看日志的姿勢:varnishncsa
Varnish的管理端口命令:varnishadm
查看varnish命中比率:varnishstat
圖標查看varnish命中:varnishhist
配置測試:
第一種測試:直接略過Varnish,直接訪問nginx測試:
通過linux自帶命令curl訪問
查看nginx日志:
第二種訪問域名,域名解析在Varnish這臺主機:
curl域名測試:
查看結果:
第三種:通過web 瀏覽器訪問,查看命中:
第四種測試:
改變index.html文件內容,測試結果:第一次都不會命中,第二次/第三次全部命中。
配置Varnish,只要是test.html文件就pass,測試結果:
以下是return (pass)和return (pipe)的區別,摘錄別人的博客:
調用 pass 函數,從后端服務器調用數據。?
?
調用 pipe 函數,建立客戶端和后端服務器之間的直接連接,從后端服務器調用數據。?
?
調用hash函數,從緩存中查找應答數據并返回,如果查找不到,則調用pass函數從后端服務器
調用數據 。?
http 建立連接的過程 ?
?
http 請求的類型:get post head?
先說http建立連接的過程
?
當瀏覽器想要獲得一個網頁內容時,如在瀏覽器輸入www.google.com。?
?
這時瀏覽器開始跟服務器建立連接,先執行三次握手,確認建立連接。?
?
之后瀏覽器會發送請求,一個網頁包含多個內容,如圖片,正文,html代碼,css代碼,js代碼。
如果在html 1.0版本中,請求一個文件是需要建立一次連接的,多個請求多個連接。開銷是很大的。
而在HTML 1.1中,具有了長連接的特性,允許在keep-live 時間內保持連接,在這段時間內無須
再建立連接就可以發送多個請求。?
?
請求完成 或 keep-live時間到限,連接斷開。?
HTTP 請求的類型:
?
HTTP 請求的類型有幾種,下面是主要的幾種:?
? GET : 請求指定的頁面信息,并返回實體主體。?
HEAD: 只請求頁面的首部。?
POST: 請求服務器接受所指定的文檔作為對所標識的URI的新的從屬實體。?
說白了,請求一個靜態的HTML頁面就是用get類型,而如果你在新浪微博上發一條微博,其實就是post 類型。
總結來說,get是請求相關URI并接受服務器的返回數據。為了接收數據。
post是發送數據給服務器,服務器需要對這些數據做相應的處理。為了發送數據。
?
以上都明白的話,就可以解答這三個問題了:
?
pass和pipe都從后端服務器取數據,它們之間有什么不同呢? ?
??
什么情況下用pass,什么情況下用pipe呢? ?
??
什么樣的數據會被緩存在varnish中呢? ?
?
問:pass和pipe都從后端服務器取數據,它們之間有什么不同呢? ?
答:當vcl_recv調用 pass 函數時,pass將當前請求直接轉發到后端服務器。而后續的請求仍然
通過varnish處理。?
例如,建立了HTTP連接之后,客戶端順序請求 a.css 、a.png兩個文件,“當前請求”指的是第一個
請求,即a.css,a.css被直接轉發到后端服務器,不被緩存。而后續的a.png則再由varnish來做
處理,varnish會判斷a.png 如何處理。?
總結:一個連接中除了當前請求,其它請求仍然按照正常情況由varnish處理。?
?
而pipe模式則不一樣,當vcl_recv判斷 需要調用 pipe 函數時,varnish會在客戶端和服務器之
間建立一條直接的連接 ,之后客戶端的所有請求都直接發送給服務器,繞過varnish,不再由varnish
檢查請求,直到連接斷開。?
?
什么情況下用pass,什么情況下用pipe呢? ?
答:pass 通常只處理靜態頁面。即只在GET 和 HEAD 類型的請求中時才適合調用pass函數。
另外,需要注意的一點是,pass模式不能處理POST請求,為什么呢?因為POST請求一般是發送
數據給服務器,需要服務器接收數據,并處理數據,反饋數據 。是動態的,不作緩存。?
示例代碼如下:?
if (req.request !="GET" && req.request != "HEAD")?
{ ? ? ? ? ? ? ??
return (pipe); ? ? ??
} ? ? ??
那什么情況下用pipe?由以上陳述可以知,類型是POST時用pipe,但是也許還不太清晰。舉個例子,
當客戶端在請求一個視頻文件時,或者一個大的文檔,如.zip .tar 文件,就需要用pipe模式,
這些大的文件是不被緩存在varnish中的。?
?
什么樣的數據會被緩存在varnish中呢? ??
答:varnish只緩存靜態數據。在網上搜到的varnish緩存策略,可以解答這個問題:?
varnish緩存策略?
?
缺省是根椐后端返回的http狀態碼決定是否緩存。可以緩存的狀態碼如下:?
200 ? ?
203 ? ?
300 ? ?
301 ? ?
302 ? ?
410 ? ?
404?
這位大師的博客鏈接:http://yeelone.blog.51cto.com/1476571/772369/
總結
- 上一篇: jQuery知识简介
- 下一篇: 利用nginx和mongrel、unic