Varnish 介紹

什麼是 Varnish , 和通常的緩存加速工具有何不同,在 Varnish 文檔中有如下描述:

1. Varnish is a reverse HTTP proxy, sometimes referred to as a HTTP accelerator or a web accelerator.
2. Varnish stores files or fragments of files in memory, allowing them to be served quickly.
3. Varnish is essentially a key/value store, that usually uses the URL as a key.
4. Varnish is designed for modern hardware, modern operating systems and modern work loads.

下面從 Varnish 的工作流程以及取數據流程兩個方面對 Varnish 的總體工作機制進行介紹。

Varnish的工作流程

Varnish 主要有兩個進程,下面是 Varnish 的基本進程結構

如上圖示,Varnish 主要存在兩個進程:manage 進程及 child 進程,其中:

  • manage 進程:更新配置,vcl 文件編譯,varnish 監控,初始化 varnish 及提供 varnish 管理介面。
  • child 進程:主要進行請求任務的處理,接受請求等。

相當於 child 進程實際是提供 Varnish 主體功能的進程,線程結構如下圖示:

child 進程中各線程的處理任務如下所示:
  • accept 線程: 監聽埠,接受連接;接受連接後組成 session 結構,查看是否有空閑線程,若有則分配給其處理,若無,則檢查等待隊列 overflow 的大小,若過大,則拋棄請求,否則加入 overflow 隊列。
  • work 線程: 從 overflow 隊列中獲取任務, 走 Varnish 狀態機流程處理任務,完成後通過 pipe 的線程通信,傳遞給 epoll 線程,等待下一個事件觸發。
  • epoll 線程:將事件發送時對應的 session , 放入 overflow 隊列,以供 work 線程從中取出繼續處理。當然,在等待事件發送時,會檢查該 session 是否過期。
  • expire 線程:對以二叉樹形式組織的緩存對象,進行過期檢查,對過期的對象進行處理(更新或者棄用)。

Varnish 中主要是在 work 線程中完成對請求的處理,而處理請求的邏輯主要是依據 varnish vcl 配置文件來決定對不同的請求採取的處理方式。vcl 配置文件主機涉及 vcl 的狀態轉換相關的配置,下面主要講 vcl 處理流程。

vcl 的處理流程

vcl 的處理流程,主要是由 Varnish 的狀態機決定,可以通過 vcl 配置文件來對 varnish 狀態機各個步驟所做的操作進行配置。

vcl 的狀態機如下圖示:

上面的狀態圖,主要對 Varnish 處理 http 請求時各個步驟及決策方式進行了描述,下面對其中的各個狀態進行介紹。

vcl_recv

vcl_recv 是 http 請求到達後進入的第一個狀態,在這個狀態中,可以對請求進行以下的一些處理:

1. 修改 client 請求,以減少緩存決策時的差異性。
2. 根據 client 請求,決定緩存策略。
3. 重定向請求
4. 決定處理請求的 backend(即後端 webserver )

在 vcl_recv 可以進入 vcl_pass, vcl_pipe,vcl_lookup,vcl_error.

vcl_pipe

若連接存活期間其請求被 vcl_recv 傳遞至 vcl_pipe ,那麼這請求後的所有請求,將直接經 vcl_recv 到達 backend,Varnish 不再查找,及存儲及請求的對象,就如同 client 與 backend 直接通信一樣, 不會記錄任何通信的日誌。

vcl_pass

進入 vcl_pass 的請求,請求會直接發送至 backend , 但不會緩存, 可進入 restart , 會增加 restart 計數。

vcl_hash

根據請求的特徵,構建 hash 值,通常是以 host+url 的形式建立 Hash 值,可進入 vcl_hit 及 vcl_miss .

vcl_hit

可進入 vcl_pass 及v cl_deliver,vcl_restart

vcl_miss

可進入 vcl_pass 及 vcl_fetch,vcl_restart

vcl_fetch

將請求傳遞至 backend, 決定是是否緩存,可進入 hit_for_pass: 僅vcl_fetch 可進入,與 pass 功能類似,不過其會利用 beresp 建立一個 hitforpass 對象,以防止同一對象被緩存,在 hitforpass 對象存在期間,同一請求的結果都不會被緩存,請求會直接進入 pass。

deliver:緩存取到的對象,並發送至服務端,也可進入 restart , 增加 restart 計數,當 restart 計數大於 max_restarts 時會報錯。

vcl_deliver

在緩存數據將要發送到客戶端時調用

vcl_error

出錯時調用,以上的各狀態通常情況下都可進入 vcl_error

對於以上狀態的轉換,具體的轉換原因,也可如下圖示:

vcl中的變數

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

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

表 2. 向後端主機請求時可用公共變數

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

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

本文作者:高志剛


推薦閱讀:
相关文章