上緩存服務器的目的:php
一、減小clint對後端服務器的訪問壓力。css
二、在靜態資源較多的狀況下,服務端能夠快速對clint的訪問作出相應。html
緩存服務器目前比較有名氣,市面上緩存代理服務器使用比較多的Varnish/squid。前端
squid的主要是緩存大文件。linux
Varnish主要緩存靜態資源,如圖片。nginx
Varnish版本的區別:git
新版本Varnish4,client/backend分離,新的vanishlog查詢語言,安全方面聽說有提高。github
首先是必須定義版本號: vcl 4.0。VMOD’s更獨立化,官方推薦是加載Standard VMOD’s(std)。web
另外director已變爲VMOD,如需使用,須要import directors。json
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。
部署架構:單節點/雙節點
一、若是大家的服務在雲節點部署那久簡單了,流行的雲平臺都有負載均衡器(HA/LB)等等,部署2臺Varnish 掛載後端nginx 就完事了。
二、若是大家自建機房,Varnish的前端代理能夠選擇(Nginx/HA),這2套開源軟件都比較流行,作代理性能也不錯。
下面是大體的Varnish邏輯圖:
第一種所有單節點:
第二種Varnish雙節點,Nginx單節點:
第三種雙節點:
Varnish的安裝上篇已經寫過,請參考以前的博客;
Varnish配置參數:
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版本了。
[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/