官术网_书友最值得收藏!

5.3 Varnish配置

Varnish狀態(tài)引擎處理流程如圖5-2所示。

102-1

圖5-2 Varnish狀態(tài)引擎處理流程圖

對圖5-2所示的流程分析如下。

vcl_recv:用于接收并處理用戶請求,當(dāng)接收到一個完整的請求時,它會檢查并分析是否可以為這個請求服務(wù),判斷請求的數(shù)據(jù)并決定如何處理請求。vcl_recv可以選擇多個策略,如1.pipe、2.lookup、3.pass。它會將控制權(quán)傳遞給下游,如vcl_pipe、vcl_hash、vcl_pass。

  • 1.1 vcl_pipe:不會緩存數(shù)據(jù),其會進(jìn)入pipe模式,由管道后端處理數(shù)據(jù),直到管道處理完畢后關(guān)閉。
  • 2.1 vcl_hash:緩存數(shù)據(jù),通過hash處理機(jī)制,默認(rèn)URL可作為key,key的方式可自定義調(diào)整,同時可以根據(jù)客戶端是否區(qū)分壓縮數(shù)據(jù)而進(jìn)一步判斷是否存儲緩存。
  • 2.2 vcl_hit:一個請求從緩存中命中需要的內(nèi)容。
  • 2.3 vcl_miss:一個請求從緩存中未命中需要的內(nèi)容。
  • 2.4/2.5 vcl_pass:對命中或未命中的數(shù)據(jù)提供數(shù)據(jù)處理功能。
  • 2.8 vcl_fetch:從后端服務(wù)器獲得請求目標(biāo)數(shù)據(jù)。
  • 2.9 deliver:從后端服務(wù)器獲得數(shù)據(jù)后,根據(jù)策略檢查是否需要緩存起來。
  • 3.1/3.2 vcl_deliver:內(nèi)容返回給客戶端。

對圖5-2所示流程中涉及的函數(shù)介紹如下。

  • pipe:將請求交給vcl_pipe函數(shù)。error code[reason]表示返回code給客戶端并放棄請求,code是錯誤標(biāo)示,例如200、405等,reason是錯誤原因。
  • vcl_pipe:該函數(shù)在進(jìn)入pipe模式時被調(diào)用,用于將請求直接傳遞給后端主機(jī),在請求和返回內(nèi)容沒有改變的情況下,將不變的內(nèi)容返回給客戶端,直到這個鏈接關(guān)閉。
  • vcl_pass:該函數(shù)在進(jìn)入pass模式時被調(diào)用,用于直接將請求發(fā)送給后端主機(jī),后端主機(jī)響應(yīng)后發(fā)送給客戶端,不進(jìn)行任何緩存,每次都返回最新內(nèi)容。
  • vcl_hash:可緩存數(shù)據(jù),通過hash機(jī)制處理,默認(rèn)將URL作為key;也可以自定義,根據(jù)客戶端是否支持處理壓縮數(shù)據(jù)來區(qū)分緩存。
  • lookup:在緩存中查找被請求的對象,并且根據(jù)查找的結(jié)果交給vcl_hit函數(shù)(命中)或vcl_miss函數(shù)(未命中)處理。
  • vcl_hit:在執(zhí)行l(wèi)ookup后,如果在緩存中命中對象,該函數(shù)將會被自動調(diào)用。
  • deliver:表示找到內(nèi)容并發(fā)送給客戶端,把控制權(quán)交給vcl_deliver函數(shù)。
  • vcl_miss:在執(zhí)行l(wèi)ookup后,如果緩存中沒有命中對象,該函數(shù)會被調(diào)用,可用于判斷是否從后端請求內(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";    // 檢查后端健康頁面
    .timeout=0.3s;                   // 過期時間
    .window=8;                       // 檢查后端服務(wù)次數(shù)
    .threshod=3;                     // 檢查后端8次訪問,若成功3次則認(rèn)為服務(wù)是存活的
    .initial=3;                      // Varnish啟動,確保多少個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;             // 定義等待連接后端的時間
    .first_byte_timeout=5s;          // 定義等待從backend傳輸過來的第一個字節(jié)的時間
    .between_byte.timeout=2s;        // 定義兩個字節(jié)的間隔時間
 }

 director zachary random{            // 隨機(jī)
    .retries=5;                      // 查找可用后端次數(shù)
    {
        .backend=zachary;            // 引用已存在的backend
        .weight=6;
    }
    {
        .backend=resource;           // 引用已存在的backend
        .weight=2;                   // 類似Nginx權(quán)重
    }
    {
        .backend={                   // 定義新的backend

        }
        .weight=2;
    }
 }

 director zachary round-robin{       // 輪詢
    {
        .backend=zachary;            // 引用已存在的backend

    }
    {
        .backend=resource;           // 引用已存在的backend

    }
    {
        .backend={                   // 定義新的backend
        }

    }
 }

 #權(quán)限訪問控制列表
 acl purgeallow {
    "127.0.0.1";
    !"192.168.0.102"
 }

 sub vcl_recv{

    if(!req.backend.healthy){
        set req.grace=30m;           // Varnish緩存時間+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緩存時間+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);
 }

對上述代碼中的重點(diǎn)流程介紹如下。

1)1個請求對應(yīng)1個backend,可配置連接后端服務(wù)。其中,connect_timeout表示連接后端超時時間,first_byte_timeout表示傳輸?shù)谝粋€字節(jié)的時間,between_byte.timeout表示第二個和第一個中間傳輸所用的時間,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)多個客戶端請求同時訪問一個頁面時,Varnish只會發(fā)送一次請求到后端,其他請求會被掛起以等待返回結(jié)果,體驗(yàn)較差。當(dāng)服務(wù)器請求流量高時,比如在秒殺活動中、同時產(chǎn)生數(shù)千萬點(diǎn)擊率時等,用戶不可能掛起等待結(jié)果。

針對以上問題,Varnish提供了Grace模式來延長緩存失效時間,即上次過期數(shù)據(jù)結(jié)果在失效時間之后延期多長時間,具體時間需根據(jù)系統(tǒng)斟酌設(shè)置,當(dāng)后端服務(wù)器出現(xiàn)問題時,負(fù)載過高后,Varnish不訪問后端直接返回舊緩存數(shù)據(jù)到客戶端。

VCL返回策略:

  • return(pass):不緩存,直接調(diào)用服務(wù)器。
  • return(lookup):先從緩存獲取,緩存中沒有數(shù)據(jù)再從服務(wù)器獲取。
  • return(pipe):當(dāng)前連接未關(guān)閉前,所有的請求都直接由服務(wù)器處理,Varnish不處理請求。
  • return(deliver):請求目標(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允許定義多個backend后端服務(wù)器。

主站蜘蛛池模板: 吴旗县| 锦屏县| 诏安县| 瑞安市| 尖扎县| 太康县| 平定县| 青神县| 凌源市| 桑植县| 万山特区| 普陀区| 西林县| 安康市| 大埔区| 平遥县| 绥芬河市| 屏边| 桓仁| 玉龙| 镇赉县| 枞阳县| 嵊州市| 简阳市| 曲周县| 镇安县| 临高县| 武宣县| 无为县| 自贡市| 巫溪县| 东海县| 阜平县| 且末县| 临洮县| 元朗区| 齐齐哈尔市| 循化| 呼伦贝尔市| 伊金霍洛旗| 买车|