varnish

Web Cache

    程序運行具有局部性:

        時間局部性

        空間局部性


    key-value:

        key: 訪問路徑,URL, hash

        value:web content


    數據具有熱點:


    緩存命中率:hit/(hit+miss)

        文檔命中率:從文檔個數進行衡量;

        字節命中率:從內容大小進行衡量;


    緩存的生命週期:
        緩存清理:緩存項過期、緩存空間耗盡;
    

    緩存與否:
        私有數據:不可緩存;


    緩存處理的步驟:
        接收請求 --> 解析請求 (提取請求的URL及各種首部)--> 查詢緩存 --> 新鮮度檢測 --> 創建響應報文 --> 發送響應 --> 記錄日誌


    緩存控制機制:
        1、過期日期:

                HTTP/1.0 Expires

                    示例:Expires:Thu, 04 Jun 2015 23:38:18 GMT           指明絕對時間,但是受時區的影響;

                HTTP/1.1 Cache-Control: max-age

                    示例:Cache-Control:max-age=3600     指明3600秒過期,相對時長;


    Cache-Control   = "Cache-Control" ":" 1#cache-directive

    cache-directive = cache-request-directive

         | cache-response-directive

    cache-request-directive =                 請求

           "no-cache"                                              

         | "no-store" (backup)                          

         | "max-age" "=" delta-seconds         

         | "max-stale" [ "=" delta-seconds ]  

         | "min-fresh" "=" delta-seconds      

         | "no-transform"                      

         | "only-if-cached"                   

         | cache-extension                   

     cache-response-directive =               響應

           "public"                                         可以放在共同緩存之上

         | "private" [ "=" <"> 1#field-name <"> ]                    只能私有緩存

         | "no-cache" [ "=" <"> 1#field-name <"> ]                可緩存,必須在響應客戶端前,驗證緩存有效與否

         | "no-store"                                                                  不可緩存

         | "no-transform"                         

         | "must-revalidate"                                                       必須做重新校驗  

         | "proxy-revalidate"                    

         | "max-age" "=" delta-seconds            

         | "s-maxage" "=" delta-seconds                                   共同緩存時長

         | cache-extension

    

        2、有效性再驗正:revalidate

                如果原始內容未改變,則僅響應首部(不附帶body部分),響應碼304 (Not Modified)

                如果原始內容發生改變,則正常響應,響應碼200;

                如果原始內容消失,則響應404,此時緩存中的緩存項也應該被刪除;


                    條件式請求首部:

                        If-Modified-Since:基於原始內容的最近一個修改時間戳進行;自從某某時間,發生改變,則返回新的內容,響應碼爲200;沒發生改變,則返回響應碼304;

                        If-Unmodified-Since:

                        If-Match:

                        If-None-Match:基於Etag(擴展標記)的比較進行;如果不匹配,則返回新的內容,響應碼爲200,否則返回響應碼304

                                示例:Etag: faiy89345


Web Cache:常見的緩存服務開源解決方案:squid, varnish

    varnish官網:https://www.varnish-cache.org


    varnish通過可以基於文件系統接口進行訪問的共享內存區域來記錄日誌(shared memory log);默認爲90M;分爲兩部分:
            前半部分是計數器
            後半部分爲客戶端請求的數據


    vcl:Varnish Configuration Language:varinish配置語言

    緩存策略配置接口;

    基於“域”的簡單編程語言;

    

    varnish緩存內容的存儲:
        (1)file:自管理的文件系統,黑盒,不支持持久機制;

        (2)malloc:使用malloc()庫調用在varnish啓動時向內存申請指定大小的空間,不支持持久機制;

        (3)persistent:與file功能相同,基於文件的持久存儲,仍處於測試期;

            

                指明緩存存儲:-s  [name=]type[,options]

                        malloc[,size]

                        file[,path[,size[,granularity]]]

                        persistent,path,size


    varnishd v4程序的選項有兩類:

            程序選項:  

                    -s,-f,...

            運行時選項:

                    -p param=value


    配置進程特性:centos7:/etc/varnish/varnish.params

    配置緩存策略:centos7:/etc/varnish/default.vcl

    服務:systemctl  start varnish.service



    vcl:“域”專用的編程語言;狀態引擎:state engine;
    VCL存在多個狀態引擎,狀態之間存在相關性,但彼此間相互隔離;每個引擎使用return(x)來退出當前狀態,並轉入下一狀態;不同狀態的引擎,其x是不盡相同;


    請求處理流程:
        (1)請求的爲可緩存:
                (a)命中:通過本地緩存響應;
                (b)未命中:到後端服務器取得響應內容;
                            可緩存對象:先緩存再響應;定義緩存時間、自定義緩存鍵;
                            不可緩存對象:不緩存而直接響應;

        (2)請求的爲不可緩存:到後端服務器取得直接響應;


    varnish finate state machine:

        vcl_rec:

                    hit:vcl_hit:
                    miss:vcl_miss

                    purge:vcl_purge

                    pipe:vcl_pipe

                    pass,hit_for_pass:vcl_pass

       vcl_hash:lookup

        

        vcl_backend_fetch

        vcl_backend_response

        vcl_backend_error


        vcl_synth


        vcl_deliver:


    數據報文處理流向:

            vcl_recv---》vcl_hash---》

                    (1)vcl_hit---》

                            (a)vcl_deliver

                            (b)vcl_pass---》vcl_backend_fetch

                    (2)vcl_miss---》

                            (a)vcl_pass

                            (b)vcl_backend_fetch

                    (3)vcl_purge---》vcl_synth

                    (4)vcl_pipe---》


            vcl_backend_fetch---》

                    vcl_backend_response---》vcl_deliver

                    vcl_backend_error


    vcl的語法:

            (1)//,#,/*...*/,:註釋

            (2)sub $name:定義子例程;

            (3)不支持循環,支持條件判斷;

            (4)有內建變量;

            (5)使用終止語句return,沒有返回值;

            (6)操作符:=,==,!=,~,&&,||


    測試使用示例1:判斷是否命中與對應的server ip;

            sub vcl_deliver{

                        if  (obj.hits>0) {

                                set resp.http.X-Cache = "HIT" + " " + server.ip;

                        } else {

                                set resp.http.X-Cache = "MISSS" + " " + server.ip;

                        }

            }


     測試使用示例2:禁止test.html使用緩存;

            sub vcl_recv{

                    if  (req.url ~ "^/test.html$") {

                            return(pass);

                    }

            }


    測試使用示例3:強制對某資源的請求不檢查緩存:

             sub vcl_recv{

                    if  (req.url ~ "(?i)~/login" || req.url ~ "(?i)^/admin" {                       //   (?i)此處表示不區分大小寫

                            return(pass);

                    }

            }


    對特定類型的資源,例如公開的圖片等,取消其私有標識,並強行設定其可以由varnish緩存的時長;

            sub vcl_backend_response{

                    if   (bereq.url ~ "(?i)\.jpg$") {

                            set beresp.ttl = 7200s;

                            unset beresp.http.Set-Cookie;

                    }

                   if   (bereq.url ~ "(?i)\.css$") {

                            set beresp.ttl = 3600s;

                            unset beresp.http.Set-Cookie;

                    }

            }



     變量:

        內建變量:
                    req*:由客戶端發來的http請求相關;

                            req.http.*:請求報文各首部;

                    bereq.*:由varnish向backend主機發出的http請求;

                    beresp.*:由backend主機發來的http響應報文;

                    resp.*:由varnish響應給客戶端的http響應報文;

                            req.http.*:響應報文的各首部;

                    obj.*:存儲在緩存空間中的緩存對象屬性;只讀;

                    client.*,server.*,storage.*:可用在所有的client side的sub routines中;

        自定義:set                    

                    

        常用的變量:

                bereq.http.HEADERS:

                bereq.request:請求方法;

                bereq.url:請求的url;
                bereq.proto:協議版本
                bereq.backend:指明要調用的後端主機;

                

                beresp.proto:

                beresp.status:響應的狀態碼;

                beresp.reason:

                beresp.backend.name:

                beresp.http.HEADERS:

                beresp.ttl:後端服務器響應中的內容的餘下的生存時長;

        

                obj.hits:此對象從緩存中命中的次數;

                obj.ttl:對象的ttl值;

        

                server.ip

                server.hostname

                server.port


                req.method:請求方法;

                req.url:請求的url;


        緩存對象修剪的方式:purge、band

            (1)purge

                        acl purgers {

                                "127.0.0.1";

                                "172.20.120.0"/23;

                        }                                    //爲purge增加訪問控制,即只允許某些主機執行purge請求method;

                       sub vcl_purge {

                            return(synth(200,"Purged."));

                        }

                        sub vcl_recv {

                            if (req.method == "PURGE")   {

                                    if (!client.ip ~ purgers) {

                                            return(synth(405,"Purging not allowed for" + client.ip));

                                    }

                                    return(purge);

                            }

                        }

                測試:curl   -X  PURGE  http://172.20.120.40/night.jpg


            

    設定多個後端服務器:

            backend appsrv {

                        .host = "172.20.120.40";

                        .port = "80";

            }

            backend default {

                        .host = "172.20.120.41";

                        .port = "80";

            }


            sub vcl_recv {

                    if (req.url ~ "(?i)\.php$") {

                            set req.backend.hint = appsrv;

                    }  else {

                            set req.backend.hint = default;

                    }

            }

      

        

        後端主機的健康狀態檢測方式:

            probe name {

                     .attribute = "value";

            }


                .url: 判定BE健康與否要請求的url; 

                .timeout =    :請求超時

                .interval =   :請求間隔

                .window =    :採樣次數

                .threshold =     :採樣次數中至少多少次成功,纔算是正常的健康狀態;


                .request=

                    "GET / HTTP/1.1"

                    "Host: 172.20.120.41"

                    "Connection: close"

                .expected_response = 200;        :期望響應狀態碼;默認爲200;


                示例1:

                backend websrv1 {

                    .host = "172.16.100.68";

                    .port = "80";

                    .probe = {

                        .url = "/test1.html";

                        .timeout = 2s;   

                        .interval =  1s; 

                        .window =   8;

                        .threshold =  4;

                    }

                }

                

                backend websrv2 {

                    .host = "172.16.100.69";

                    .port = "80";

                    .probe = {

                        .url = "/test1.html";

                        .timeout = 2s;   

                        .interval =  1s; 

                        .window =   8;

                        .threshold =  4;

                    }

                }

                

                sub vcl_recv {

                    if (req.url ~ "(?i)\.(jpg|png|gif)$") {

                        set req.backend_hint = websrv1;

                    } else {

                        set req.backend_hint = websrv2;

                    }

                }


                示例2:定義後端服務負載均衡:

                import directors; 

                sub vcl_init {

                    new mycluster = directors.round_robin();

                    mycluster.add_backend(websrv1);

                    mycluster.add_backend(websrv2);

                }

                

                vcl_recv {

                set req.backend_hint = mycluster.backend();

                }

                

                負載均衡算法:

                fallback, random, round_robin, hash

     

                                       

    varnish命令行工具:

            varnishadm -S /etc/varnish/secret -T IP:PORT        :連接到varnish,查看其狀態;

                     varnish>

                            param.show    :查看運行參數

                            param.set        :設置運行參數

            varnishtop            :對varnish日誌信息排序等

            varnishncsa            :以apache、ncsa格式顯示日誌信息,可以以服務模式啓動:varnishncsa.service

            varnishlog                :顯示原始日誌,可以以服務模式啓動:varnishlog.service

            varnishstat            :顯示varnish的緩存統計信息


    varnish的線程模型:

            cache-worker線程

            cache-main線程:此線程只有一個,用於啓動caceh;

            ban luker:

            acceptor:

            epoll:線程池管理器

            expire:清理過期緩存

            

varnish定義其最大併發連接數:線程池模型:

            thread_pools:線程池個數;默認爲2;

            thread_pool_max:單線程池內允許啓動的最多線程個數;

            thread_pool_min

            thread_pool_timeout:多於thread_pool_min的線程空閒此參數指定的時長後即被purge;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章