varnish配置詳解

轉自:http://blog.csdn.net/keda8997110/article/details/8777153

Varnish配置文件詳解

既然Varnish需要在多臺服務器上緩存數據,就需要Varnish映射所有的URL到一臺單獨的主機。


  1. backend webserver {  
  2. .host = "127.0.0.1";  
  3. .port = "80";  
  4. .connect_timeout = 4s;  
  5. .first_byte_timeout = 5s;  
  6. .between_bytes_timeout = 20s;  
  7. }  

該塊配置用於定義一臺Varnish默認訪問的後端服務器,當Varnish需要從後端服務器獲取數據時,就會訪問自己的80端口。

當然Varnish也可以定義多臺後端服務器實現負載均衡的目的。

.connect_timeout定義的是等待連接後端的時間

.first_byte_timeout定義的是等待從backend傳輸過來的第一個字節的時間

.between_bytes_timeout 定義的是兩個字節的間隔時間

當然還可以增加一個backend,用於訪問本機的8090端口,假設通過該端口提供圖片服務。


  1. backend img {  
  2. .host = "127.0.0.1";  
  3. .port = "8090";  
  4. }  

 

當匹配img的URL時,需把請求發送到上面定義的backend img,其他的請求發送到backend webserver。

  1. sub vcl_recv {  
  2. if (req.url ~ "^/img/") {  
  3. set req.backend = img;  
  4. } else {  
  5. set req.backend = webserver.  
  6. }  
  7. }  

 

Varnish不僅僅可以定義多個backend,還可以把多個backend合成一個組,使用循環的方式把請求分配給組中的backends。並且Varnish會根據健康檢查情況來判斷後端服務器是否正常提供服務。

Varnish使用區域語言VCL來管理定義Varnish的存取策略。VCL語法簡單,跟Perl比較相似,可以使用多種運算符如"="、"=="、"!,&&,!!"等形式;也可以使用正則表達式來進行匹配,還可以使用"set"來指定變量。當執行VCL時,Varnish會先把VCL轉換成二進制代碼。

有一點要注意,"\"字符在VCL裏沒有什麼特別的含義,這點和其他語言不同。另外,VCL只是配置語言,並不是真正的編程語言,所以沒有循環和自定義變量。

爲了可以更好地對Varnish進行配置調整,需要了解Varnish的配置語法,也就是VCL語言。下面對VCL常用的一些函數和變量進行介紹。

(1)vcl_recv模塊

用於接收和處理請求。當請求成功被調用後,Varnish通過判斷請求的數據來決定如何處理請求。此模塊一般以如下幾個關鍵字結束。

pass:表示進入pass模式,把請求交給vcl_pass模塊處理。

pipe:表示進入pipe模式,把請求交給vcl_pipe模塊處理。

error code [reason]:表示把錯誤標識返回給客戶端,並放棄處理該請求。錯誤標識包括200、405等。"reason"是對錯誤的提示信息。

(2)vcl_pipe模塊

此模塊在請求進入pipe模式時被調用,用於將請求直接傳遞至後端主機,在請求和返回的內容沒有改變的情況下,也就是在當前連接未關閉時,服務器將不變的內容返回給客戶端,直到該連接被關閉。

(3)vcl_pass模塊

此模塊表示當請求被pass後,用於將請求直接傳遞至後端應用服務器。後端應用服務器在接收請求後將數據發送給客戶端,但不進行任何數據的緩存,在當前連接下每次都返回最新的內容。

(4)lookup

一個請求在vcl_recv中被lookup後,Varnish將在緩存中提取數據。如果緩存中有相應的數據,就把控制權交給vcl_hit模塊;如果緩存中沒有相應的數據,請求將被設置爲pass並將其交給vcl_miss模塊。

(5)vcl_hit模塊

執行lookup指令後,Varnish在緩存中找到請求的內容後將自動調用該模塊。

在此模塊中,deliver表示將找到的數據發送給客戶端,並把控制權交給vcl_deliver模塊。

(6)vcl_miss模塊

執行lookup後,Varnish在緩存中沒有找到請求的內容時會自動調用該方法。此模塊可以用於判斷是否需要從後端服務器獲取內容。

在此模塊中,fetch表示從後端獲取請求的數據,並把控制權交給vcl_fetch模塊。

(7)vcl_fetch模塊

在後端主機更新緩存並且獲取內容後調用該方法,接着,通過判斷獲取的內容來決定是將內容放入緩存,還是直接返回給客戶端。

(8)vcl_deliver模塊

當一個沒有被緩存的數據交付給客戶端的時候被調用。

(9)vcl_timeout 模塊

在緩存數據到期前調用此模塊。

在此模塊中,discard表示從緩存中清除到期數據。

(10)vcl_discard模塊

在緩存數據到期後或緩存空間不夠時,自動調用該模塊。

在此模塊中keep表示將數據繼續保留在緩存中。


  1. acl purge {  
  2.        "localhost";  
  3.        "127.0.0.1";  
  4.        "18.81.12.10";  
  5. }  
  6.  
  7.  
  8.        if (req.request == "PURGE") {  
  9.                if (!client.ip ~ purge) {  
  10.                        error 405 "Not allowed.";  
  11.                }  
  12.                return(lookup);  
  13.        }  



這兩個規則定義了允許哪些主機通過HTTP來執行PURG進行緩存刪除。如果不是指定的IP,就會出現HTTP 405錯誤,提示Not allowed錯誤字樣。

  1. if (req.http.host ~ "^(read)?.aaa.com$") {  
  2.              set req.backend = webserver;   
  3.              if (req.request != "GET" && req.request != "HEAD") {  
  4.                      return(pipe);  
  5.              }  
  6.              else {  
  7.                      return(lookup);  
  8.              }  
  9.      }  
  10.      else {  
  11.              error 404 " Cache Server";   
  12.              return(lookup);  
  13.      }  

這段條件判斷用於對aaa.com域名進行緩存加速,aaa.com是泛指概念,也就是說所有以aaa.com結尾的域名都進行緩存。而if (req.request != "GET" && req.request != "HEAD") 表示"如果請求的類型不是GET與HEAD",則返回錯誤碼404。

  1. if (req.url ~ "^/images") {  
  2.   unset req.http.cookie;  
  3.  }  

這條規則的意思是清除服務器上/images目錄下的所有緩存,當這個請求在後端服務器生效時,如果訪問的URL匹配這個規則,那麼頭信息中的cookie就會被刪除。


  1. if (req.request == "GET" && req.url ~ "\. (png|swf|txt|png|gif|jpg|css|js|htm| html)$") {  
  2.   unset req.http.cookie;  
  3.  }  
  4.  
  5.  
  6. if (req.http.x-forwarded-for) {   
  7.         set reqreq.http.X-Forwarded-For =   
  8.                 req.http.X-Forwarded-For ", " client.ip; }   
  9. else { set req.http.X-Forwarded-For = client.ip; }  

因爲Squid、Varnish都會把客戶端的IP地址放在HTTP_X_FORWARDED_FOR裏面傳給後端的Web服務器,所以後端的Web程序都要對其進行調用。

  1. if (req.request != "GET" &&  
  2.     req.request != "HEAD" &&  
  3.     req.request != "PUT" &&  
  4.     req.request != "POST" &&  
  5.     req.request != "TRACE" &&  
  6.     req.request != "OPTIONS" &&  
  7.     req.request != "DELETE") {  
  8.   return (pipe);  
  9.  }  


該if判斷表示如果請求的類型不是GET、HEAD、PUT、POST、TRACE、OPTIONS、DELETE時,則進入pipe模式。注意這裏的"&&"是與的關係。

  1. if (req.request == "GET" && req.url ~ "\. (png|swf|txt|png|gif|jpg|css|js|htm| html)") {  
  2.                set beresp.ttl = 180s;  
  3.        }  
  4.        else {  
  5.                set beresp.ttl = 30d;  
  6.        }  
  7.         return (deliver);  
  8. }  

 

該if判斷用於對請求類型是GET,並且請求的URL以png、swf、txt、gif、css、js等結尾時,則進行緩存,緩存時間爲180秒。其他緩存爲30天。

  1. sub vcl_deliver {  
  2.  set resp.http.x-hits = obj.hits ;  
  3.  if (obj.hits > 0) {  
  4.   set resp.http.X-Cache = "HIT read.easouu.com";  
  5.  }  
  6.  else {  
  7.       set resp.http.X-Cache = "MISS read.easou.com";  
  8.  }  

 

這個模塊定義的是添加一個Header標識,以判斷緩存是否命中。

  1. sub vcl_error {  
  2.  set obj.http.Content-Type = "text/html; charset=utf-8";  
  3.  synthetic {"  
  4. <?xml version="1.0" encoding="utf-8"?> 
  5. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict// EN" "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-strict.dtd"> 
  6. <html> 
  7.    <head> 
  8.       <title>"} obj.status " " obj.response {"</title> 
  9.    </head> 
  10.    <body> 
  11.       <h1>Error "} obj.status " " obj.response {"</h1> 
  12.       <p>"} obj.response {"</p> 
  13.       <h3>Guru Meditation:</h3> 
  14.       <p>XID: "} req.xid {"</p> 
  15.       <hr> 
  16.       <address> 
  17.          <a href="http://read.easou.com/">read.easou.com</a> 
  18.       </address> 
  19.    </body> 
  20. </html> 
  21. "};  
  22.  return (deliver);  
  23. }  

最後這個模塊定義了訪問錯誤頁面時的返回信息。

現在varnish配置基本完成,可以在8080端口上啓動varnish,並進行一些基本的測試。

Varnish緩存的配置

簡單的配置文件內容如下:


  1. [html] view plaincopy
    1. backend webserver {    
    2. .host = "127.0.0.1";    
    3. .port = "8090";    
    4. .connect_timeout = 4s;    
    5. .first_byte_timeout = 5s;    
    6. .between_bytes_timeout = 20s;    
    7. }    
    8. acl purge {    
    9.        "localhost";    
    10.        "127.0.0.1";    
    11.        "18.81.12.10";    
    12. }    
    13.    
    14. sub vcl_recv {    
    15.    
    16.        if (req.request == "PURGE") {    
    17.                if (!client.ip ~ purge) {    
    18.                        error 405 "Not allowed.";    
    19.                }    
    20.                return(lookup);    
    21.        }    
    22.    
    23.        if (req.http.host ~ "^(read)?.easou.com$") {    
    24.                set req.backend = webserver;     
    25.                if (req.request != "GET" && req.request != "HEAD") {    
    26.                        return(pipe);    
    27.                }    
    28.                else {    
    29.                        return(lookup);    
    30.                }    
    31.        }    
    32.        else {    
    33.                error 404 " Cache Server";     
    34.                return(lookup);    
    35.        }    
    36.    
    37.  if (req.request == "GET" && req.url ~ "\.(png|swf|txt|png|gif|jpg|css|js| htm|html)$") {    
    38.   unset req.http.cookie;    
    39.  }    
    40.    
    41.  if (req.url ~ "^/images") {    
    42.   unset req.http.cookie;    
    43.  }    
    44.    
    45.      if (req.http.Cache-Control ~ "(no-cache|max-age=0)") {    
    46.         purge_url(req.url);     
    47.      }     
    48.      return (lookup);    
    49.    
    50. if (req.http.x-forwarded-for) {     
    51.         set reqreq.http.X-Forwarded-For =     
    52.                 req.http.X-Forwarded-For ", " client.ip; }     
    53. else { set req.http.X-Forwarded-For = client.ip; }    
    54.    
    55.    
    56. if (req.request != "GET" &&    
    57.     req.request != "HEAD" &&    
    58.     req.request != "PUT" &&    
    59.     req.request != "POST" &&    
    60.     req.request != "TRACE" &&    
    61.     req.request != "OPTIONS" &&    
    62.     req.request != "DELETE") {    
    63.   return (pipe);    
    64.  }    
    65.    
    66.  if (req.request != "GET" && req.request != "HEAD") {    
    67.   return (pass);    
    68.  }     
    69.    
    70.  if (req.http.Authorization || req.http.Cookie) {    
    71.   return (pass);    
    72.  }    
    73. }    
    74.  sub vcl_pipe {    
    75.       # set req.http.connection = "close";    
    76.      return (pipe);}    
    77.  sub vcl_hit {    
    78.  if (!obj.cacheable) {    
    79.   return (pass);    
    80.  }    
    81.  if (req.request == "PURGE") {    
    82.          set obj.ttl = 0s;    
    83.          error 200 "Purged.";    
    84.       }    
    85.  return (deliver);    
    86. }    
    87.    
    88. sub vcl_miss {    
    89.  return (fetch);    
    90. }    
    91.    
    92.    
    93. sub vcl_fetch {    
    94.    
    95. if (!beresp.cacheable) {    
    96.  return (pass);    
    97.  }    
    98.  if (beresp.http.Set-Cookie) {    
    99.   return (pass);    
    100.  }    
    101.    
    102.  if (beresp.http.Pragma ~ "no-cache" ||    
    103.      beresp.http.Cache-Control ~ "no-cache" ||    
    104.             beresp.http.Cache-Control ~ "private") {    
    105.   return (pass);    
    106.       }    
    107.    
    108. if (req.url ~ "^/cover/") {    
    109.                set beresp.ttl = 1800s;    
    110.        }    
    111.        else {    
    112.                set beresp.ttl = 30d;    
    113.        }    
    114.          return (deliver);    
    115.    
    116.           
    117. #       if (req.request == "GET" && req.url ~ "\.(png|swf|txt|png|gif|jpg|css|js| htm|html|jsp)") {    
    118. #               set beresp.ttl = 180s;    
    119. #       }    
    120. #       else {    
    121. #               set beresp.ttl = 30d;    
    122. #       }    
    123. #        return (deliver);    
    124. }    
    125.    
    126. sub vcl_deliver {    
    127.  set resp.http.x-hits = obj.hits ;    
    128.  if (obj.hits > 0) {    
    129.   set resp.http.X-Cache = "HIT read.easouu.com";    
    130.  }    
    131.  else {    
    132.       set resp.http.X-Cache = "MISS read.easou.com";    
    133.  }    
    134. }    
    135. sub vcl_error {    
    136.  set obj.http.Content-Type = "text/html; charset=utf-8";    
    137.  synthetic {"    
    138. <?xml version="1.0" encoding="utf-8"?>   
    139. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-strict.dtd">   
    140. <html>   
    141.    <head>   
    142.       <title>"} obj.status " " obj.response {"</title>   
    143.    </head>   
    144.    <body>   
    145.       <h1>Error "} obj.status " " obj.response {"</h1>   
    146.       <p>"} obj.response {"</p>   
    147.       <h3>Guru Meditation:</h3>   
    148.       <p>XID: "} req.xid {"</p>   
    149.       <hr>   
    150.       <address>   
    151.          <a href="http://read.easou.com/">read.easou.com</a>   
    152.       </address>   
    153.    </body>   
    154. </html>   
    155. "};    
    156.  return (deliver);    
    157. }    

    Varnish 簡介

    Varnish 是一款高性能且開源的反向代理服務器和 HTTP 加速器,其採用全新的軟件體系機構,和現在的硬件體系緊密配合,與傳統的 squid 相比,varnish 具有性能更高、速度更快、管理更加方便等諸多優點,很多大型的網站都開始嘗試使用 varnish 來替換 squid,這些都促進 varnish 迅速發展起來。

    挪威的最大的在線報紙 Verdens Gang(vg.no) 使用 3 臺 Varnish 代替了原來的 12 臺 Squid,性能比以前更好,這是 Varnish 最成功的應用案例。

    Varnish 文件緩存的工作流程

    Varnish 與一般服務器軟件類似,分爲 master 進程和 child 進程。Master 進程讀入存儲配置文件,調用合適的存儲類型,然後創建 / 讀入相應大小的緩存文件,接着 master 初始化管理該存儲空間的結構體,然後 fork 並監控 child 進程。Child 進程在主線程的初始化的過程中,將前面打開的存儲文件整個 mmap 到內存中,此時創建並初始化空閒結構體,掛到存儲管理結構體,以待分配。Child 進程分配若干線程進行工作,主要包括一些管理線程和很多 worker 線程。

    接着,開始真正的工作,varnish 的某個負責接收新 HTTP 連接線程開始等待用戶,如果有新的 HTTP 連接過來,它總負責接收,然後喚醒某個等待中的線程,並把具體的處理過程交給它。Worker 線程讀入 HTTP 請求的 URI,查找已有的 object,如果命中則直接返回並回複用戶。如果沒有命中,則需要將所請求的內容,從後端服務器中取過來,存到緩存中,然後再回復。

    分配緩存的過程是這樣的:它根據所讀到 object 的大小,創建相應大小的緩存文件。爲了讀寫方便,程序會把每個 object 的大小變爲最接近其大小的內存頁面倍數。然後從現有的空閒存儲結構體中查找,找到最合適的大小的空閒存儲塊,分配給它。如果空閒塊沒有用完,就把多餘的內存另外組成一個空閒存儲塊,掛到管理結構體上。如果緩存已滿,就根據 LRU 機制,把最舊的 object 釋放掉。

    釋放緩存的過程是這樣的:有一個超時線程,檢測緩存中所有 object 的生存期,如果超初設定的 TTL(Time To Live)沒有被訪問,就刪除之,並且釋放相應的結構體及存儲內存。注意釋放時會檢查該存儲內存塊前面或後面的空閒內存塊,如果前面或後面的空閒內存和該釋放內存是連續的,就將它們合併成更大一塊內存。

    整個文件緩存的管理,沒有考慮文件與內存的關係,實際上是將所有的 object 都考慮是在內存中,如果系統內存不足,系統會自動將其換到 swap 空間,而不需要 varnish 程序去控制。

    Varnish 安裝

    下載 varnish 安裝包

    建議下載最新穩定版本(現在最新 varnish 版本爲 3.0.2),varnish 提供源代碼安裝包和可執行程序安裝包,按照您的習慣下載適合您平臺的任一安裝包即可。

    安裝 varnish

    源代碼安裝包安裝

    首先安裝 pcre 庫,pcre 庫是爲兼容正則表達式,如果不安裝,在安裝 varnish2.0 版本以上時,會提示找不到 pcre 庫。以下是 pcre 的安裝過程,其代碼如清單 1 所示:


    清單 1. pcre 庫安裝代碼
    				
         tar zxvf pcre.tar.gz 
         cd pcre/ 
         ./configure --prefix=/usr/local/pcre/ 
         Make && make install 
    

    安裝 varnish,其代碼如清單 2 所示:


    清單 2. varnish 安裝代碼
    				
            tar xzvf varnish-3.0.2.tar.gz 
            cd varnish-3.0.2 
            export PKG_CONFIG_PATH =/usr/local/pcre/lib/pkgconfig 
            ./configure --prefix=/usr/local/varnish  	
            make 
            make install 
    

    可執行程序安裝包安裝

    RedHat 系統環境下的安裝 varnish,您需要安裝以下軟件:automake、autoconf、libtool、ncurses-devel、libxslt、groff、pcre-devel、pkgconfig,然後進行 varnish 的安裝,安裝代碼如清單 3 所示:


    清單 3. varnish 安裝代碼
    				
     rpm -i varnish-2.1.4-2.el5.x86_64.rpm 
    

    啓動 varnish


    清單 4. varnish 啓動代碼
    				
     varnishd -f /etc/varnish/default.vcl -s file,/var/varnish_cache,1G \
     -T 127.0.0.1:2000 -a 0.0.0.0:9082
    

    各參數的含義如下:

    -f 指定 varnish 的配置文件位置

    -s 指定 varnish 緩存存放的方式,常用的方式有:“-s file,<dir_or_file>,<size>”。

    -T address:port 設定 varnish 的 telnet 管理地址及其端口

    -a address:port 表示 varnish 對 http 的監聽地址及其端口

    Varnish 配置

    VCL 簡介

    VCL(varnish configuration language)是 varnish 配置語言,其用來定義 varnish 的存取策略。VCL 語法比較簡單,跟 C 和 Perl 比較相似。主要有以下幾點:

    • 塊是由花括號分隔,語句以分號結束,使用‘ # ’符號可以添加註釋。
    • VCL 使用指定運算符“=”、比較運算符“==”、邏輯運算符“!,&&,!!”等形式,還支持正則表達式和用“~”進行 ACL 匹配運算。
    • VCL 沒有用戶自己定義的變量,你可以在 backend、request 或 object 上設置變量值,採用 set 關鍵字進行設置。例如 set req.backend = director_employeeui;
    • 兩個字符串的連接,他們之間沒有任何運算符。代碼如清單 5 所示:

    清單 5. 字符串連接代碼
    				
     set req.http.X-hit = " hit" "it"; 
    

    • \”字符在 VCL 裏沒有特別的含義,這點與其他語言略有不同。
    • VCL 可以使用 set 關鍵字設置任何 HTTP 頭,可以使用 remove 或是 unset 關鍵字移除 HTTP 頭。
    • VCL 有 if/else 的判斷語句,但是沒有循環語句。

    VCL backend

    聲明並初始化一個後端對象,代碼如清單 6 所示


    清單 6. backend 聲明代碼
    				
    	 backend www { 
    	   .host = "www.example.com"; 
    	   .port = "9082"; 
    	 } 
    

    後端對象的使用,代碼如清單 7 所示


    清單 7. backend 的使用代碼
    				
    	 if (req.http.host ~ "^(www.)?example.com$") { 
    	    set req.backend = www; 
    	 } 
    

    VCL 後端的集合 director

    VCL 可以把多個 backends 聚合成一個組,這些組被叫做 director,這樣可以增強性能和彈力,當組裏一個 backend 掛掉後,可以選擇另一個健康的 backend。VCL 有多種 director,不同的 director 採用不同的算法選擇 backend,主要有以下幾種:

    • The random director

    Random director 會根據所設置的權值(weight)來選擇 backend,.retries 參數表示嘗試找到一個 backend 的最大次數,.weight 參數表示權值

    • The round-robin director

    Round-robin director 在選擇 backend 時,會採用循環的方式依次選擇。

    • The client director

    Client director 根據 client.identity 來選擇 backend,您可以設置 client.identity 的值爲 session cookie 來標識 backend。

    backend probes

    VCL 可以設置 probe 來檢測一個 backend 是否健康,定義一個 backend probes 代碼如清單 8 所示:


    清單 8. 定義 backend probes 代碼
    				
    	 backend www { 
    	  .host = "www.example.com"; 
    	  .port = "9082"; 
    	  .probe = { 
    	    .url = "/test.jpg";// 哪個 url 需要 varnish 請求
    	    .timeout = 1 s;// 等待多長時間超時
    	    .interval = 5s// 檢查的時間間隔
                 .window = 5;// 維持 5 個 sliding window 的結果
    	    .threshold = 3;// 至少有三次 window 是成功的,就宣告 backend 健康
    	  } 
    	 } 
    

    ACL

    ACL 可創建一個客戶端的訪問控制列表,你可以使用 ACL 控制哪些客戶端可以訪問,哪些客戶端禁止訪問。定義 ACL 代碼如清單 9 所示:


    清單 9. ACL 定義代碼
    				
    	 Acl local{ 
    	   "localhost"; 
    	   "192.0.2.0"/24; 
    	   !"192.0.2.23";// 除去該 IP 
    	 } 
    

    VCL 內置函數

    vcl_recv 函數

    用於接收和處理請求。當請求到達併成功接收後被調用,通過判斷請求的數據來決定如何處理請求。例如如何響應、怎麼響應、使用哪個後端服務器等。

    此函數一般以如下幾個關鍵字結束。

    pass:表示進入 pass 模式,把請求控制權交給 vcl_pass 函數。

    pipe:表示進入 pipe 模式,把請求控制權交給 vcl_pipe 函數。

    lookup:表示進入 lookup 模式,把請求控制權交給 lookup 指令處理,在緩存中查找被請求的對象,並且根據查找的結果把控制權交給函數 vcl_hit 或函數 vcl_miss。

    error code [reason]:表示返回“code”給客戶端,並放棄處理該請求。“code”是錯誤標識,例如 200 和 405 等。“reason”是錯誤提示信息。

    vcl_pipe 函數

    此函數在進入 pipe 模式時被調用,用於將請求直接傳遞至後端主機,在請求和返回的內容沒有改變的情況下,將不變的內容返回給客戶端,直到這個連接被關閉。

    此函數一般以如下幾個關鍵字結束。

    error code [reason]。

    pipe。

    vcl_pass 函數

    此函數在進入 pass 模式時被調用,用於將請求直接傳遞至後端主機。後端主機在應答數據後將應答數據發送給客戶端,但不進行任何緩存,在當前連接下每次都返回最新的內容。

    此函數一般以如下幾個關鍵字結束。

    error code [reason]。

    pass。

    restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告

    vcl_hash

    當您想把一個數據添加到 hash 上時,調用此函數。

    此函數一般以如下幾個關鍵字結束。

    Hash。

    vcl_hit 函數

    在執行 lookup 指令後,在緩存中找到請求的內容後將自動調用該函數。

    此函數一般以如下幾個關鍵字結束。

    deliver:表示將找到的內容發送給客戶端,並把控制權交給函數 vcl_deliver。

    error code [reason] 。

    pass。

    restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告

    vcl_miss 函數

    在執行 lookup 指令後,在緩存中沒有找到請求的內容時自動調用該方法。此函數可用於判斷是否需要從後端服務器獲取內容。

    此函數一般以如下幾個關鍵字結束。

    fetch:表示從後端獲取請求的內容,並把控制權交給 vcl_fetch 函數。

    error code [reason] 。

    pass。

    vcl_fetch 函數

    在後端主機更新緩存並且獲取內容後調用該方法,接着,通過判斷獲取的內容來決定是將內容放入緩存,還是直接返回給客戶端。

    此函數一般以如下幾個關鍵字結束。

    error code [reason]。

    pass。

    deliver。

    esi。

    restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告

    vcl_deliver 函數

    將在緩存中找到請求的內容發送給客戶端前調用此方法。

    此函數一般以如下幾個關鍵字結束。

    error code [reason]。

    deliver。

    restart 重新啓動流程,增加啓動次數,如果重新啓動次數高於 max_restarts 發出一個錯誤警告

    vcl_error

    出現錯誤時調用此函數。

    此函數一般以如下幾個關鍵字結束。

    deliver。

    restart。

    VCL 處理流程

    VCL 處理的流程圖如圖 1 所示


    圖 1.VCL 處理流程
    圖 1.VCL 處理流程 

    Varnish 處理 HTTP 請求的過程大致分爲如下幾個步驟。

    • Receive 狀態(vcl_recv)。也就是請求處理的入口狀態,根據 VCL 規則判斷該請求應該 pass(vcl_pass)或是 pipe(vcl_pipe),還是進入 lookup(本地查詢)。
    • Lookup 狀態。進入該狀態後,會在 hash 表中查找數據,若找到,則進入 hit(vcl_hit)狀態,否則進入 miss(vcl_miss)狀態。
    • Pass(vcl_pass)狀態。在此狀態下,會直接進入後端請求,即進入 fetch(vcl_fetch)狀態
    • Fetch(vcl_fetch)狀態。在 fetch 狀態下,對請求進行後端獲取,發送請求,獲得數據,並根據設置進行本地存儲。
    • Deliver(vcl_deliver)狀態。將獲取到的數據發給客戶端,然後完成本次請求。

    VCL 內置公共變量

    VCL 內置的公共變量可以用在不同的 VCL 函數中,下面根據使用的不同階段進行介紹

    當請求到達時,可以使用的公共變量表 1 所示


    表 1. 請求到達時可用公共變量
    公共變量名 含義
    req.backend 指定對應的後端主機
    server.ip 表示服務器 IP
    client.ip 表示客戶端 IP
    req.quest 只是請求的類型,例如 GET、HEAD 等
    req.url 指定請求的地址
    req.proto 表示客戶端發起請求的 HTTP 協議版本
    req.http.header 表示對應請求中的 HTTP 頭部信息
    req.restarts 表示重啓次數,默認最大值爲 4

    Varnish 在向後端主機請求時,可是用的公共變量如表 2 所示


    表 2. 向後端主機請求時可用公共變量
    公共變量名 含義
    beresp.requset 指定請求類型,例如 GET、HEAD 等
    beresp.url 表示請求地址
    beresp.proto 表示客戶端發起請求的 HTTP 協議版本
    beresp.http.header 表示對應請求中 HTTP 頭部信息
    beresp.ttl 表示緩存的生存週期,cache 保留時間(s)

    從 cache 或是後端主機獲取內容後,可以使用的公共變量如表 3 所示


    表 3. 後端主機獲取內容時可使用公共變量
    公共變量名 含義
    obj.status 返回內容的請求狀態碼,例如 200、302、504 等
    obj.cacheable 返回的內容是否可以緩存
    obj.valid 是否有效的 HTTP 請求
    obj.response 返回內容的請求狀態信息
    obj.proto 返回內容的 HTTP 版本
    obj.ttl 返回內容的生存週期,也就是緩存時間,單位秒
    obj.lastuse 返回上一次請求到現在的時間間隔,單位秒

    對客戶端應答時,可以使用的公共變量如表 4 所示


    表 4. 對客戶端相應時可使用公共變量
    公共變量名稱 含義
    resp.status 返回給客戶端的 HTTP 代碼狀態
    resp.proto 返回給客戶端的 HTTP 協議版本
    resp.http.header 返回給客戶端的 HTTP 頭部消息
    resp.response 返回給客戶端的 HTTP 頭部狀態

    VCL 調試

    VCL 爲配置文件語言,無法像 c/c++ 那樣進行單步調試,當 VCL 運行的效果和預期效果不一樣時,很難發現哪出現邏輯錯誤,這時除了查看代碼查找錯誤外,我們還可以採用內置 C 語言和瀏覽器查看返回對象中的狀態來查找邏輯的錯誤。

    我們可以採用內置 C 語言來打印相應的信息,例如我們可以在相應的地方打印信息,來查看 VCL 流程的執行是否正確。內置 C 語言打印信息代碼如清單 10 所示:


    清單 10. 打印信息代碼
    				
          C{ 
    	    #include<syslog.h>// 首先要包含頭文件
          }C 
          C{ 
    	    Syslog(LOG_INFO,"VCL run here in function xxx in line xxx"); 
          }C 
    

    啓動 varnish 後,我們可以採用 tail -f /var/log/messages 命令在 /var/log/messages 中查看相應的打印信息。查看的打印信息如圖 2 所示:


    圖 2. varnish 打印信息
    圖 2. varnish 打印信息 

    我們還可以將某些變量的值設置到返回給瀏覽器的對象上,然後在瀏覽器中查看該變量的值。設置變量值代碼如清單 11 所示:


    清單 11. varnish 變量設置代碼
    				
     set beresp.http.X-Cookie-Debug-req-cookie = req.http.Cookie; 
    

    在 chrome 瀏覽器中查看 beresp.http.X-Cookie-Debug-req-cookie 的值,結果如圖 3 所示:


    圖 3. 在瀏覽器中查看 varnish 變量的值
    圖 3. 在瀏覽器中查看 varnish 變量的值 

    varnish 配置文件代碼


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