Varnish 入門

jopen 12年前發布 | 27K 次閱讀 Varnish 緩存服務器

本文將介紹 varnish 的工作流程,安裝以及 varnish 的配置三個方面的內容。首先簡單的介紹 varnish 以及其工作流程,大概了解其內部原理,然后介紹了 varnish 的安裝方法,最后詳細介紹了 varnish 的配置語言 VCL 以及如何對 VCL 進行調試。最后附有一份詳細注釋的 varnish 配置文件代碼。

本文將詳細介紹 varnish 的工作流程、安裝、配置三個方面。相信閱讀完本文,讀者能熟練掌握 varnish。

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 庫安裝代碼

</tr> </tbody> </table>

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


清單 2. varnish 安裝代碼

tar zxvf pcre.tar.gz 
     cd pcre/ 
     ./configure --prefix=/usr/local/pcre/ 
     Make && make install

</tr> </tbody> </table>

可執行程序安裝包安裝


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


清單 3. 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

</tr> </tbody> </table>

啟動 varnish


清單 4. varnish 啟動代碼

rpm -i varnish-2.1.4-2.el5.x86_64.rpm

</tr> </tbody> </table>

各參數的含義如下:

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

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

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

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

Varnish 配置

VCL 簡介

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

  • 塊是由花括號分隔,語句以分號結束,使用‘ # ’符號可以添加注釋。
  • </ul>

    • VCL 使用指定運算符“=”、比較運算符“==”、邏輯運算符“!,&&,!!”等形式,還支持正則表達式和用“~”進行 ACL 匹配運算。
    • </ul>

      • VCL 沒有用戶自己定義的變量,你可以在 backend、request 或 object 上設置變量值,采用 set 關鍵字進行設置。例如 set req.backend = director_employeeui;
      • </ul>

        • 兩個字符串的連接,他們之間沒有任何運算符。代碼如清單 5 所示:
        • </ul>
          清單 5. 字符串連接代碼

varnishd -f /etc/varnish/default.vcl -s file,/var/varnish_cache,1G \
 -T 127.0.0.1:2000 -a 0.0.0.0:9082

</tr> </tbody> </table>

  • \”字符在 VCL 里沒有特別的含義,這點與其他語言略有不同。
  • </ul>

    • VCL 可以使用 set 關鍵字設置任何 HTTP 頭,可以使用 remove 或是 unset 關鍵字移除 HTTP 頭。
    • </ul>

      • VCL 有 if/else 的判斷語句,但是沒有循環語句。
      • </ul>

        VCL backend

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


        清單 6. backend 聲明代碼

set req.http.X-hit = " hit" "it";

</tr> </tbody> </table>

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


清單 7. backend 的使用代碼

backend www { 
       .host = "www.example.com"; 
       .port = "9082"; 
     }

</tr> </tbody> </table>

VCL 后端的集合 director

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

  • The random director
  • </ul>

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

    • The round-robin director
    • </ul>

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

      • The client director
      • </ul>

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

        backend probes

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


        清單 8. 定義 backend probes 代碼

if (req.http.host ~ "^(www.)?example.com$") { 
        set req.backend = www; 
     }

</tr> </tbody> </table>

ACL

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


清單 9. ACL 定義代碼

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 健康
      } 
     }

</tr> </tbody> </table>

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 處理流程
Varnish 入門

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

  • Receive 狀態(vcl_recv)。也就是請求處理的入口狀態,根據 VCL 規則判斷該請求應該 pass(vcl_pass)或是 pipe(vcl_pipe),還是進入 lookup(本地查詢)。
  • </ul>

    • Lookup 狀態。進入該狀態后,會在 hash 表中查找數據,若找到,則進入 hit(vcl_hit)狀態,否則進入 miss(vcl_miss)狀態。
    • </ul>

      • Pass(vcl_pass)狀態。在此狀態下,會直接進入后端請求,即進入 fetch(vcl_fetch)狀態
      • </ul>

        • Fetch(vcl_fetch)狀態。在 fetch 狀態下,對請求進行后端獲取,發送請求,獲得數據,并根據設置進行本地存儲。
        • </ul>

          • Deliver(vcl_deliver)狀態。將獲取到的數據發給客戶端,然后完成本次請求。
          • </ul>

            VCL 內置公共變量

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

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


            表 1. 請求到達時可用公共變量

Acl local{ 
       "localhost"; 
       "192.0.2.0"/24; 
       !"192.0.2.23";// 除去該 IP 
     }

</tr>

</tr>

</tr>

</tr>

</tr>

</tr>

</tr>

</tr>

</tr> </tbody> </table>

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


表 2. 向后端主機請求時可用公共變量

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

</tr>

</tr>

</tr>

</tr>

</tr>

</tr> </tbody> </table>

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


表 3. 后端主機獲取內容時可使用公共變量

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

</tr>

</tr>

</tr>

</tr>

</tr>

</tr>

</tr>

</tr> </tbody> </table>

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

表 4. 對客戶端相應時可使用公共變量

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

</tr>

</tr>

</tr>

</tr>

</tr> </tbody> </table>

VCL 調試

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

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


清單 10. 打印信息代碼

公共變量名稱 含義
resp.status 返回給客戶端的 HTTP 代碼狀態
resp.proto 返回給客戶端的 HTTP 協議版本
resp.http.header 返回給客戶端的 HTTP 頭部消息
resp.response 返回給客戶端的 HTTP 頭部狀態

C{

    #include<SYSLOG.H>// 首先要包含頭文件
  }C 
  C{ 
    Syslog(LOG_INFO,"VCL run here in function xxx in line xxx"); 
  }C</SYSLOG.H></pre></td>

</tr> </tbody> </table>

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


圖 2. varnish 打印信息
Varnish 入門

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


清單 11. varnish 變量設置代碼

</tr> </tbody> </table>

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


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



小結

本文介簡單介紹了 varnish,并對其工作流程、安裝以及配置進行了詳細講解。通過本文,可以很快的掌握 varnish。

來自: IBM developerWorks

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
set beresp.http.X-Cookie-Debug-req-cookie = req.http.Cookie;
  • sesese色