Varnish部署


上緩存服務器的目的: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邏輯圖:

第一種所有單節點:

wKioL1kLBk2iZxL6AABLM0_SbKg584.png


第二種Varnish雙節點,Nginx單節點:

wKioL1kLBn6Tf3otAABfg78JJN4551.png


第三種雙節點:

wKioL1kLBq3T8-APAAB1PhnSBsA411.png


 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

wKiom1kLCWChUWe9AAD3u2Unuio395.png


查看Varnish的日誌常被緩存的資源:varnishlog

wKiom1kLCbfhitSdAAEnBrvqJKk244.png


另外一種查看日誌的姿式:varnishncsa

wKiom1kLCqWgBKQAAABFr73tPBE351.png


Varnish的管理端口命令:varnishadm

wKiom1kLC2ThWRCqAAB8S9zSnz8047.png


查看varnish命中比率:varnishstat

wKioL1kLC6mAxgEMAADFbfWpSuM682.png

圖標查看varnish命中:varnishhist

wKioL1kLEpiTnJ-wAABtYyX5IJs927.png

配置測試:

第一種測試:直接略過Varnish,直接訪問nginx測試:

經過linux自帶命令curl訪問

wKiom1kLEw2D2fcOAABM2H1DE2I047.png

查看nginx日誌:

wKiom1kLEzHQAfUBAAC2meT4Qcw289.png


第二種訪問域名,域名解析在Varnish這臺主機:

curl域名測試:

wKiom1kLE2vSKKQQAACjsWhk7fo894.png

查看結果:

wKiom1kLE4LxEWO4AAA3PKV3dlw251.png


第三種:經過web 瀏覽器訪問,查看命中:

wKioL1kLE7SSzuvlAAKrVLw04QA642.png

第四種測試:

改變index.html文件內容,測試結果:第一次都不會命中,第二次/第三次所有命中。

wKiom1kLFCTCekZXAACjsWhk7fo218.png

配置Varnish,只要是test.html文件就pass,測試結果:

wKiom1kLFG6iPIbuAACNPYAJdWQ252.png


如下是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/

相關文章
相關標籤/搜索