Varnish

varnish

一、簡介

   Varnish是一款高性能的開源HTTP加速器,挪威最大的在線報紙 Verdens Gang 使用3臺Varnish代替了原來的12臺Squid,性能比以前更好。

   Varnish 的作者Poul-Henning Kamp是FreeBSD的內核開發者之一,他認爲現在的計算機比起1975年已經複雜許多。在1975年時,儲存媒介只有兩種:內存與硬盤。但現在計算機系統的內存除了主存外,還包括了CPU內的L1、L2,甚至有L3快取。硬盤上也有自己的快取裝置,因此Squid Cache自行處理物件替換的架構不可能得知這些情況而做到最佳化,但操作系統可以得知這些情況,所以這部份的工作應該交給操作系統處理,這就是 Varnish cache設計架構。

   varnish項目是2006年發佈的第一個版本0.9.距今已經八年多了,此文檔之前也提過varnish還不穩定,那是2007年時候編寫的,經過varnish開發團隊和網友們的辛苦耕耘,現在的varnish已經很健壯。很多門戶網站已經部署了varnish,並且反應都很好,甚至反應比squid還穩定,且效率更高,資源佔用更少。相信在反向代理,web加速方面,varnish已經有足夠能力代替squid。

   varnish的官網爲https://www.varnish-cache.org,rpm,rpm包的下載位置爲:http://repo.varnish-cache.org。

二、關於Varnish

1.varnish系統架構

   varnish主要運行兩個進程:Management進程和Child進程(也叫Cache進程)。

   Management進程主要實現應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個命令行接口等。Management進程會每隔一段時間探測一下Child進程以判斷其是否正常運行,如果在指定的時長內未得到Child進程的迴應,Mangagement將會重啓此Child進程。

   Child進程包含多種類型的線程,常見的如:

       Acceptor進程:接受新的連接請求並響應

       worker進程:child進程會爲每個用戶啓動一個worker進程,因此,在高併發的場景中可能會出現數百個worker進程甚至更多

       Expiry進程:從緩存中清理過期內容

       Varnish依賴“工作區(workspace)”以降低線程在申請或修改內存時出現競爭的可能性。在varnish內部有多種不同的工作區,其中最關鍵的當屬用於管理會話數據的session工作區

2.varnish日誌

   爲了與系統的其他部分進行交互,Child進程使用了可以通過文件系統接口進行訪問的共享內存日誌(shared memory log),因此,如果某線程需要記錄信息,其僅需要持有一個鎖,而後向共享內存中的某內存區域寫入數據,再釋放持有的鎖即可。而爲了減少競爭,每個worker線程都使用了日誌數據緩存

   共享內存大小一般爲90M,其分爲兩部分,前一部分爲計數器,後半部分爲客戶端請求的數據。varnish通過了多個不同的工具,如varnishlog、varnishncsa或varnishstst等來分析共享內存日誌中的信息並能夠以指定的方式進行顯示

   3.varnish的後端存儲

     varnish支持多種不同類型的後端存儲。這可以在varnish啓動時使用-s選項指定。後端存儲的類型包括

     (1)file:使用特定的文件存儲全部的緩存數據,並通過操作系統的mmap()系統調用整個緩存文件映射至內存區域(如果條件允許)

     (2)mallco: 使用mallco()庫調用在varnish啓動時向操作系統申請指定的大小的內存空間以存儲緩存數據

     (3)persistent(experimental):與file的功能相同,但是可以持久存儲數據(即重啓varnish時數據不會被清楚),仍處於測試階段

     varnish無法追蹤某緩存對象是否存入了緩存文件,而後也就無法得知磁盤上的緩存文件是否可用,因此,file存儲在varnish停止或重啓是會清除數據。而persistent方法的出現對此有一個彌補,但persistent仍處於測試階段,例如目前尚無法有效處理要緩存對象總體大小超出緩存空間的情況,所有,其僅適用於有着巨大緩存空間的場景。

    選擇使用合適的存儲方式有助於途勝系統性能,從經驗的角度來看,建議在內存空間足以存儲所有數據的緩存對象時使用malloc的方法,反之,file存儲將會有着更好的性能表現,然而,需要注意的是,varnishd實際上是用的空間比使用-s選項指定的緩存空間更大,一般說來,其需要爲每個緩存對象多使用差不多1k左右的存儲空間,這意味着,對於100萬個緩存對象來說,其使用的緩存空間將超出指定大小1G左右,另外,爲了保存數據結構等,varnish自身也會佔去不少的內存空間。

    爲varnish指定使用的緩存類型時,-s選項可接受的參數格式如下:

       malloc[,size]或file[,path[,size[,granularity]]]或persistent,path,size{experimental}

三、VCL

   1.簡介

     VCL(Varnish Configuration Language)是varnish配置緩存策略的工具,它是一種基於“域”(domain specific)的簡單編程語言,他支持有限的算術運算和邏輯運算操作、允許使用正則表達式進行字符串匹配、允許用戶使用set自定義變量、支持if判斷語句,也要內置的函數和變量等。使用VCL編寫的緩存策略通常保存至.vcl文件中,其需要編譯成二進制的格式後纔能有varnish調用。事實上,整個緩存策略就是由幾個特定的子歷程如vcl_recv、vcl_fetch等組成,他們分別在不同的位置(或時間)執行,如果沒有實現爲某個位置自定義子例程,varnish將會執行默認的定義

    VCL策略在啓用前,會由management進程將其轉換爲C代碼,而後再有gcc編譯器將C代碼編譯成二進制程序。編譯完成後,management負責將其連接至varnish實例,即Child進程。正式由於編譯工作在child進程之外完成,它避免了轉載錯誤格式VCL的風險,因此,varnish修改配置的開銷非常小,其可以同時保有幾分尚在引用的舊版本配置,也能夠讓新的配置即刻生效,編譯後的舊版本配置通常在varnish重啓時纔會被丟棄,如果需要手動清理,則可以使用varnishadm的vcl.discard命令來完成

2.VCL狀態引擎

    在VCL狀態引擎中,狀態之間具有相關性,但彼此間互相隔離,每個引擎使用return(x)來退出當前狀態並指示varnish進入下一個狀態

    varnish開始處理一個請求時,首先需要分析HTTP請求本身,比如從首部獲取請求方法、驗證其是否爲一個合法的HTTP請求等,當這些基本分析結束後就需要做出第一個決策,即varnish是否從緩存中查找請求的資源,這個決定的實現則需要有VCL來完成,簡單來說,要有vcl_recv方法來完成,如果說管理員沒有定義vcl_recv函數,varnish將會執行默認的vcl_recv函數,然而,即便管理員自定義了vcl_recv,但如果沒有爲自定義的vcl_recv函數指定其終止操作(terminating),其仍將會指定默認的vcl_recv函數,事實上,varnish官方強烈建議讓varnish執行默認的vcl_recv以便處理自定義vcl_recv函數中可能出現的漏洞

3.VCL語法

    VCL的設計參考了C和perl語言,因此,對有着C或Perl編程經驗者來說,其非常容易理解。其基本語法說明如下:

    (1)//、#或/* comment */用於註釋

    (2)sub $name 定義函數

    (3)不支持循環,有內置變量

    (4)使用終止語句,沒有返回值

    (5)域專用

    (6)操作符:=(賦值)、==(等值比較)、~(模式匹配)、!(非,取反)、&&(邏輯與)、||(邏輯或)

    VCL的函數不接受參數並且沒有返回值,因此,其並非真正意義上的函數,這也限定了VCL內部的數據傳遞只能隱藏在HTTP首部內部進行。VCL的return語句用於將控制權從VCL狀態引擎返回給varnish,而非默認函數,這就是爲什麼VCL只有終止語句而沒有返回值的原因,同時,對於每個“域”來說,可以定義一個或多個終止語句,以告訴varnish下一步採取何種操作,如查詢緩存或不查詢緩存

4.VCL的內置函數

     VCL提供了結果函數來實現字符串的修改,如添加bans,重啓VCL狀態引擎因將控制權轉回varnish等

    regsub(str,reget,sub):基於正則表達式搜索指定的字符串並將其替換成指定的字符串,只替換匹配到的第一個

    regsuball(str,reget,sub):基於正則表達式搜索指定的字符串並將其統統替換成指定的字符串

    ban(expression):

    ban_url(regex):Bans所有其URL能夠由regex匹配的緩存對象

    purge:從緩存中挑選出某對象以及其相關變種一併刪除,這可以通過通過HYTP協議的PURGE方法完成

    hash_data(str):

    return():當某個VCL與運行結束時,將控制權返回給Varnish,並指示Varnish如何進行後續的操作:其可以返回的指令包括:lookup、pass、pipe、hit_for_pass、fetch、deliver和hash等:但某特定域可能技能返回某些特定的指令,而非前面列出的全部指令:

    return(restart):重新運行整個VCL,即重新從vcl_recv開始進行處理;每一次重啓都會增加req.restaets變量中的值,而max_restaets參數則用於限定最大重啓次數

5.vcl_recv

     vcl_recv是在varnish完成對請求報文的解碼爲基本數據結構後第一個要指定的子例程,他通常有四個主要用途:

     (1)修改客戶端數據以減少緩存對象差異性,比如刪除URL中的www.等字符串

      (2)基於客戶端數據選用緩存策略:比如僅緩存特定的額URL請求、不緩存POST請求等

     (3)爲某web應用程序執行URL重寫

     (4)挑選合適的後端服務器;

    可以使用下面的終止語句,即通過return()向varnish返回指示操作

      pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;

      pipe:不對客戶端進行檢查或做出任何操作,而是在客戶端與後端服務器之間建立專業“通道”,並直接將數據在二者之間進行傳送:此時,keep-alive連接中後續傳送的數據也都將在通過此管道進行直接傳送,並不會出現在任何日誌中

      lookup:在緩存中查找用戶請求的對象,如果緩存中沒有其指定的對象,後續操作很可能會將其請求的對象進行緩存

      error:有varnish自己合成一個響應報文,一般是響應一個錯誤類信息、重定向類信息或緩存均衡器返回的後端web服務器健康狀態檢查類信息

     vcl_recv也可以通過精巧的策略完成一定意義上的安全功能,以將某特定的***扼殺於搖籃中,同時,它也可以檢查出一些拼寫的錯誤並將其進行修改

     varnish默認的vcl_recv專門設計用來實現安全的緩策略,它主要完成兩種功能:

       (1)僅處理可以識別的HTTP方法,並且只緩存GET和HEAD方法

       (2)不緩存任何用戶特有的數據

     安全起見,一般都在自定義的vcl_recv中不要使用return()終止語句,而是再由默認vcl_recv進行處理,並有其做出響應的的處理決策

6.vcl_fetch

     如前面所述,想對於vcl_recv是根據客戶端的請求做出緩存策略來說,vcl_fetch則是根據服務器端的響應做出緩存決策,在任何VCL狀態引擎中發揮pass操作都將有vcl_fetch進行後續處理。vcl_fetch中有許多可用的內置變量,比如最常見的用於定義某對象緩存時長的beresp.ttl變量,通過return()返回給varnish的操作指令有:

       deliver:緩存此對象,並將其發送給客戶端(經由vcl_deliver)

       hit_for_pass:不緩存此對象,但可以導致後續對此對象的請求直接送達到vcl_pass進行處理

       restart:重啓整個VCL,並增加重啓次數,超出max_restarts限定的最大重啓次數將會發揮錯誤信息

       error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

      默認的vcl_fetch放棄了緩存任何使用了Set-Cookie首部的響應

7.vcl_deliver

     在緩存中找到緩存內容,發送給客戶端時調用此參數,通過return()返回給varnish的操作指令有:  

       deliver:緩存此對象,並將其發送給客戶端(經由vcl_deliver)

       error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

8.val_pass

      此函數在進入pass模式時被調用,用於將請求直接傳遞至後端主機,後端主機應答數據後發送給客戶端,但是不緩存任何數據,在當前連接下,每次都是犯回最新的內容,通過return()返回給varnish的操作指令有:  

        error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

        pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;

9.vcl_pipe

       不對客戶端進行檢查或做出任何操作,而是在客戶端與後端服務器之間建立專業“通道”,並直接將數據在二者之間進行傳送:此時,keep-alive連接中後續傳送的數據也都將在通過此管道進行直接傳送,並不會出現在任何日誌中,通過return()返回給varnish的操作指令有:  

         error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

        pipe:不對客戶端進行檢查或做出任何操作,而是在客戶端與後端服務器之間建立專業“通道”,並直接將數據在二者之間進行傳送:此時,keep-alive連接中後續傳送的數據也都將在通過此管道進行直接傳送,並不會出現在任何日誌中

10.lookup

      表示在緩存裏查找被請求的對象,並且根據查找的數據把控制權交給vcl_miss或vcl_hit

11.vcl_hit

       在執行lookup指令後,如果在緩存中找到請求的內容,將自動調用此函數,通過return()返回給varnish的操作指令有:

        deliver:緩存此對象,並將其發送給客戶端(經由vcl_deliver)

        error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

         pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;

12.vcl_miss函數

      在執行lookup指令後,如果在緩存中找不到請求的內容,將自動調用此函數,此函數可以判斷是否在後端服務器上獲取內容,通過return()返回給varnish的操作指令有:

         error code [reson]:返回指定的錯誤代碼給客戶端並丟棄此請求,“code”是錯誤標識,例如200、405等,“reason”是錯誤提示信息。

         pass:繞過緩存,即不從緩存中查詢內容或不將內容存儲至緩存中;

13.VCL處理流程圖

       通過上面對VCL函數的介紹,大家應該對每個函數實現的功能有一個瞭解,,起始每個函數之間是有聯繫的,如下圖所示

wKioL1cVu3LCOv4kAAFmr2HtAaw854.jpg 


狀態引擎:

1:vcl_recv    2:vcl_pipe   3:vcl_pass   4:vcl_hash    5:vcl_hit   6:vcl_miss   7:vcl_fetch   8:vcl_delier  

9:vcl_error


緩存的處理步驟:

   接受請求---解析請求---查詢緩存---新鮮度檢查---創建響應報文---發送響應---記錄日誌

 

緩存的新鮮度檢測方法:

  (1)過期時間:

         HTTP/1.0   

             Expires:"Mon, 21 Mar 2016 05:02:19 GMT"   固定時間來檢測

                    HTTP/1.1

             Cache-Control:"max-age=900"  這種最多存活時時間來檢測

 

  (2)有效性再驗證:revalidate

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

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

          如果原始內容消失,響應爲404,些時緩存中cache object 也應該被刪除

   

   (3)條件式請求首部:

 

            根據時間戳判斷:

     If-Modified-Since: 自從請求的時間之後,請求的資源是否發生過修改,用時間戳驗證

     If-Unmodified-Since:自從請求的時間之後,請求的資源是否發沒有修改

      

      根據標籤來判斷:

     If-None-Match :本地緩存中存儲的文檔的Etag標籤是否與服務器文檔的Etag不匹配。

     If-Match :本地緩存中存儲的文檔的Etag標籤是否與服務器文檔的Etag匹配。

 

yum 安裝 varnish

# yum insatll varnish-libs-3.0.4-1.el6.x86_64.rpm varnish-3.0.4-1.el6.x86_64.rpm 

 wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-3.0.5-1.el6.x86_64.rpm 

wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-libs-3.0.5-1.el6.x86_64.rpm

wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/varnish-docs-3.0.5-1.el6.x86_64.rpm

1:

# vi /etc/sysconfig/varnish

修改一下參數
VARNISH_LISTEN_PORT=80                     //表示將varnish對外的監聽端口改爲80

 VARNISH_STORAGE="malloc,100M"             //將數據緩存在內存中,內存大小爲100M

其餘的使用默認即可


2:

置varnish

     本處使用varnishadm命令行接口來刷新varnish

      命令格式:varnishadm [-n ident] [-t timeout] [-S secretfile] -T [address]:port command [...]

      通過命令行的方式連接至varnishd進行管理操作的工具,指定要連接的varnish實例有兩種方法:

       -T [address]:port 來接指定套接字上的實例

       -n ident 連接指定名稱的實例

    其運行模式有兩種,當不在命令行中給出指定要指定的“command”時,要將進入交互模式,否則,varnish將指定指定的“command”並退出。


# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082

 varnishadm 使用:

   vcl.load

   vcl.use

   vcl.show

   vcl.discard


varnish 一般只對 get head 緩存


backend storage:支持緩存存儲內型有3種

         -s type 

        malloc  [,size]   //內存中緩存

    file[,path[,size[,granularity]]]         //一個文件保存所有緩存

    persistent,path,size {experimental}      // 在具體生並環境中不建議用,

 

varnishl 裏可用單分支和多分支判斷

 

varnish 裏可用變量:

 1:常用變量,在任何引擎中都可以用的,

    new           // 獲取當前系統的當前時間

   .host          //後端主機的ip

   .port         //後斷主機的端口

 

2:用於處理請求階段

   client.ip                 // 客戶機ip

   server.hostname      // 服務器主機名(varnish服務器名)

   server.ip              // 務器主ip   (varnish ip)

   server.port         //服務器端口    (varnish 端口)

 

   req.request    //請求方法

   req.url           // 請求url

   req.porto        //請求協議

   req.backend       //用於服務此次請求的後端主機

   req.backend.healthy   //後端健康狀態

   req.http.HEADER    //引用請求報文中指定的首部

   req.hash-always_miss 

   req.hash-ignore_busy

   req.can_gzip      //客戶端是否能接受gzip 壓縮的內容

   req.restarts     //此請求被重啓的請求

 

3: varnish自己 向backend 主機發起請求前可用的變量

   bereq.request    //varnish 對後端口請求方法

   bereq.url            //varnish 對後端口請求url

   bereq.proto       //varnish 對後端請求協議

   bereq.http.HEADER    //varnish 對後端口請求頭

   bereq.connect_timeout     //等待與backend主機發起的連接超時時長

 

   4:backend主機的響應報文到達varnish主機後,將其放放置於cache中之前可用的變量。

   beresp.do_stream    // 流式響應

   beresp.do_gzip        //  是否壓縮後存入cache

   beresp.do_gunzip    //   是否解壓後存入緩存。

   beresp.http.HEADER   // 響應時頭

   beresp.proto             // 響應時協議

   beresp.status           //  響應狀態碼

   beresp.response        // 響應時的原因短語

   beresp.ttl                  // 響應對象的剩餘生存時長,單位爲秒

   beresp.backend.name   // 相應報文來源的backend名稱

   beresp.backend.ip        //   響應時報文來源的backend IP

   beresp.backend.port    //   響應時報文來源的backend 端口

   beresp.storage            //響應的存儲後端

  

  5:緩存對象存入的ccache之後可用的變量

obj,proto           //響應時協議

obj.status        // 響應時狀態碼

obj.response  

obj.hits           //響應時次數

obj.ttl  

obj,http,HEADER    // 響應首部

 

  6:在決定對請求鍵做hash計算時可用的變量

     req.hash

     

  7:在爲客戶端準備響應時報文可用變量

   resp.proto

   resp.status

   resp.response

   resp.http.HEADER

 

狀態引擎:

  vcl_init: 在裝載vcl,用其處理請求之前

  vcl_recv: 請求被接入,但在其分析,處理完成之前。

             是否服務些請求,如何服務,使用那個後端主機服務

  vcl_fetch:從後端口主機收到相應報文之前被調用

      deliver

              error code 給個錯誤碼

             restart 重啓請求

       



 

warnish param的查看和修改:

varnish> param.show -l

修改鏈接池一些值,但是這種方法只對當前有效果

varnish> param.set thread_pool_max 4000      修改線程池個數

200 

 

varnish 線程模型:

 cache-worker 線程

 cache-mian 線程:些線程只有一個,用來啓動cache

 ban luker:

 acceptor:

 epoll: 線程池管理

 expire: 清理過期緩存

 

 

thread_pool_add_delay       2 [milliseconds]

thread_pool_add_threshold   2 [requests]

thread_pool_fail_delay      200 [milliseconds]

thread_pool_max             3000 [threads] 單個線程池啓動最多線程個數

thread_pool_min             50 [threads]

thread_pool_purge_delay     1000 [milliseconds]  每一秒清理一次緩存,請保留默認

thread_pool_stack           unlimited [bytes]

thread_pool_timeout         120 [seconds]  線程池的超時時間,

thread_pool_workspace       65536 [bytes]  線程池默認使用多少內存,建議默認

thread_pools                2 [pools]     線程池管理

thread_stats_rate           10 [requests]

 

 

varnish的命令行工具:

(1)varnishadm

(2)varnishtop:內存日誌區域查看工具

  RxHeader User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebK

it/53

  RxHeader:爲tag,基於標籤過慮,可用-i-x 選項,

  User-Agent 爲起始內容。稱爲日誌消息。用-I-X過濾

-I regexp:僅顯示被模式匹配到的條目

-X regexp:僅顯示不被模式匹配到的條目

-C:忽略大小寫

-d:顯示已有日誌

 

(3)varnishstat  緩存統計

-l 列出所有字段

-f 統計字段  -f後接的字段名

-x:xml輸出格式

-j:json 格式輸出

 

配置文件:

sub vcl_deliver {

     if (obj.hits>0) {

       set resp.http.X-Cache = "HIT";

     } else {

       set resp.http.X-Cache = "MISS";

     }

     return (deliver);

 }

下面爲varnish 配置樣本

backend default {

  .host = "192.168.1.105";

  .port = "80";

}

acl purgers {

        "127.0.0.1";

        "192.168.1.0"/24;

}

# Below is a commented-out copy of the default VCL logic.  If you

# redefine any of these subroutines, the built-in logic will be

# appended to your code.

 sub vcl_recv {

     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.request == "PURGE") {

                if (!client.ip ~ purgers) {

                        error 405 "Method not allowed";

                }

                return (lookup);

        }

     if (req.request != "GET" &&

       req.request != "HEAD" &&

       req.request != "PUT" &&

       req.request != "POST" &&

       req.request != "TRACE" &&

       req.request != "OPTIONS" &&

       req.request != "DELETE" &&

       req.request != "PURGE") {

     #    /* Non-RFC2616 or CONNECT which is weird. */

         return (pipe);

     }

     if (req.request != "GET" && req.request != "HEAD" && req.request !="PURGE") {

      #  /* We only deal with GET and HEAD by default */

         return (pass);

     }

     if (req.http.Authorization || req.http.Cookie) {

  #       /* Not cacheable by default */

         return (pass);

     }

     return (lookup);

 }


# sub vcl_pipe {

#     # Note that only the first request to the backend will have

#     # X-Forwarded-For set.  If you use X-Forwarded-For and want to

#     # have it set for all requests, make sure to have:

#     # set bereq.http.connection = "close";

#     # here.  It is not set by default as it might break some broken web

#     # applications, like IIS with NTLM authentication.

#     return (pipe);

# }

 sub vcl_pass {

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

                error 502 "PURGE on a passed object";

        }

     return (pass);

 }

# sub vcl_hash {

#     hash_data(req.url);

#     if (req.http.host) {

#         hash_data(req.http.host);

#     } else {

#         hash_data(server.ip);

#     }

#     return (hash);

# }

 sub vcl_hit {

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

                purge;

                error 200 "Purged";

        }

     return (deliver);

 }


 sub vcl_miss {

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

                purge;

                error 404 "Not in cache";

        }

     return (fetch);

 }


# sub vcl_fetch {

#     if (beresp.ttl <= 0s ||

#         beresp.http.Set-Cookie ||

#         beresp.http.Vary == "*") {

#               /*

#                * Mark as "Hit-For-Pass" for the next 2 minutes

#                */

#               set beresp.ttl = 120 s;

#               return (hit_for_pass);

#     }

#     return (deliver);

# }

 sub vcl_deliver {

     if (obj.hits>0) {

       set resp.http.X-Cache = "HIT";

     } else {

       set resp.http.X-Cache = "MISS";

     }

     return (deliver);


 }


# sub vcl_error {

#     set obj.http.Content-Type = "text/html; charset=utf-8";

#     set obj.http.Retry-After = "5";

#     synthetic {"

# <?xml version="1.0" encoding="utf-8"?>

# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

#  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

# <html>

#   <head>

#     <title>"} + obj.status + " " + obj.response + {"</title>

#   </head>

#   <body>

#     <h1>Error "} + obj.status + " " + obj.response + {"</h1>

#     <p>"} + obj.response + {"</p>

#     <h3>Guru Meditation:</h3>

#     <p>XID: "} + req.xid + {"</p>

#     <hr>

#     <p>Varnish cache server</p>

#   </body>

# </html>

# "};

#     return (deliver);

# }

# sub vcl_init {

#       return (ok);

# }

# sub vcl_fini {

#       return (ok);


配置範例2:


probe chk {

  .url = "/test.html";

  .window = 5;

  .threshold = 3;

  .interval = 3s;

  .timeout = 1s;

  }

backend web1 {

  .host = "192.168.1.104";

  .port = "80";

  .probe = chk;

}

backend web2 {

  .host = "192.168.1.105";

  .port = "80";

  .probe = chk;

}


director webservers random {

  .retries = 5;

  {

    .backend = web1;

    .weight = 1;

  }


   {

    .backend = web2;

    .weight = 1;

  }

}

acl purgers {

        "127.0.0.1";

        "192.168.1.0"/24;

}

# Below is a commented-out copy of the default VCL logic.  If you

# redefine any of these subroutines, the built-in logic will be

# appended to your code.

 sub vcl_recv {

     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.request ~ "test.html") {

        set req.backend = web1;

        } else {

        set req.backend = webservers;

        }

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

                if (!client.ip ~ purgers) {

                        error 405 "Method not allowed";

                }

                return (lookup);

        }

     if (req.request != "GET" &&

       req.request != "HEAD" &&

       req.request != "PUT" &&

       req.request != "POST" &&

       req.request != "TRACE" &&

       req.request != "OPTIONS" &&

       req.request != "DELETE" &&

       req.request != "PURGE") {

     #    /* Non-RFC2616 or CONNECT which is weird. */

         return (pipe);

     }

     if (req.request != "GET" && req.request != "HEAD" && req.request !="PURGE") {

      #  /* We only deal with GET and HEAD by default */

         return (pass);

     }

     if (req.http.Authorization || req.http.Cookie) {

  #       /* Not cacheable by default */

         return (pass);

     }

     return (lookup);

 }


# sub vcl_pipe {

#     # Note that only the first request to the backend will have

#     # X-Forwarded-For set.  If you use X-Forwarded-For and want to

#     # have it set for all requests, make sure to have:

#     # set bereq.http.connection = "close";

#     # here.  It is not set by default as it might break some broken web

#     # applications, like IIS with NTLM authentication.

#     return (pipe);

# }

 sub vcl_pass {

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

                error 502 "PURGE on a passed object";

        }

     return (pass);

 }

# sub vcl_hash {

#     hash_data(req.url);

#     if (req.http.host) {

#         hash_data(req.http.host);

#     } else {

#         hash_data(server.ip);

#     }

#     return (hash);

# }

 sub vcl_hit {

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

                purge;

                error 200 "Purged";

        }

     return (deliver);

 }


 sub vcl_miss {

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

                purge;

                error 404 "Not in cache";

        }

     return (fetch);

 }


# sub vcl_fetch {

#     if (beresp.ttl <= 0s ||

#         beresp.http.Set-Cookie ||

#         beresp.http.Vary == "*") {

#               /*

#                * Mark as "Hit-For-Pass" for the next 2 minutes

#                */

#               set beresp.ttl = 120 s;

#               return (hit_for_pass);

#     }

#     return (deliver);

# }

 sub vcl_deliver {

     if (obj.hits>0) {

       set resp.http.X-Cache = "HIT";

     } else {

       set resp.http.X-Cache = "MISS";

     }

     return (deliver);


 }


# sub vcl_error {

#     set obj.http.Content-Type = "text/html; charset=utf-8";

#     set obj.http.Retry-After = "5";

#     synthetic {"

# <?xml version="1.0" encoding="utf-8"?>

# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

#  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

# <html>

#   <head>

#     <title>"} + obj.status + " " + obj.response + {"</title>

#   </head>

#   <body>

#     <h1>Error "} + obj.status + " " + obj.response + {"</h1>

#     <p>"} + obj.response + {"</p>

#     <h3>Guru Meditation:</h3>

#     <p>XID: "} + req.xid + {"</p>

#     <hr>

#     <p>Varnish cache server</p>

#   </body>

# </html>

# "};

#     return (deliver);

# }

# sub vcl_init {

#       return (ok);

# }

# sub vcl_fini {

#       return (ok);

# }




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