varnish配置語言(1)


知識來源爲官方文檔:
《Varnish用戶指南》
《Varnish4.0電子書》前端

經過對varnish原理的學習,咱們知道varnish緩存策略是基於VCL語言實現,處理邏輯是編寫在.vcl配置文件中
涉及的總要知識點有如下幾個web

  1. vcl語法:運算符、條件語句、子程序、關鍵字
  2. 內置Subroutines
  3. Request and response VCL objects
  4. action:return(action)
  5. Functions:內建函數
  6. Variables:變量

1. vcl語法

varnish 4.0版本開始,vcl擁有本身的默認規則,它不可移除,老是追加在自定義的規則以後。正則表達式

  • vcl配置文件以 vcl 4.0 開頭;
  • C語言註釋風格://or#or/* foo */;
  • 子函數使用sub關鍵字聲明, 例如sub vcl_recv { ...};
  • 無循環, state-limited variables(受限於引擎的內建變量);
  • 使用return(action)中斷引擎狀態,指向下一步處理,action爲關鍵字 ,例如: return(pass);
  • 可動態裝載;

VCL4相比VCL3語法的改變點express

  • 要在配置文件中指定版本:即在第一行寫上 vcl 4.0;
  • vcl_fetch函數被vcl_backend_response代替,且req.*再也不適用vcl_backend_response;
  • 後端源服務器組director成爲varnish模塊,需import directors後再在vcl_init子例程中定義;
  • vcl_error變動爲vcl_backend_error,必須使用beresp.,而不是obj.
  • req.request變動爲req.method,obj爲只讀對象了。
  • 自定義的子例程(即一個sub)不能以vcl_開頭,調用使用call sub_name;
  • error()函數被synth()替代;
  • return(lookup)被return(hash)替代;
  • 使用beresp.uncacheable建立hit_for_pss對象;
  • 變量req.backend.healty被std.healthy(req.backend)替代;
  • 變量req.backend被req.backend_hint替代;
  • 關鍵字remove被unset替代;
  • 關鍵字"purge"命令,已被去除。在vcl_recv使用return(purge)。
  • vcl_synth採用resp.,而非原來的obj.

1.1 主體語法

sub subroutine {
...
}
if CONDITION {
...
} else {
...
}
return()  # Functions
hash_data() # Functions

1.2 操做符

= 賦值
== 等於
~ 匹配,能夠與正則表達式或ACL一塊兒使用。同時注意匹配的規則若是是字符串,則須要 " " 引發。
! 邏輯非
&& 邏輯與
|| 邏輯或

1.3 Subroutines

子例程
子例程用於對代碼進行分組以提升可讀性或可重用性,例:後端

sub pipe_if_local {
    if (client.ip ~ localnetwork) {
        return (pipe);
    }
}

VCL中的子例程不帶參數,也不返回值。內置子例程的名稱均以vcl_開頭。
要調用子例程,請使用call關鍵字,後跟子例程的名稱:緩存

sub vcl_recv {
    call pipe_if_local;
}

Varnish具備許多內置的子例程,這些子例程在每次事務流經Varnish時都會被調用。這些內置的子例程都名爲vcl_*。您本身的子例程不能以vcl_開頭其名稱。服務器

Return
當執行return(action)語句時,正在進行的vcl_ *子例程執行結束。
該操做指定執行的方式。上下文定義了可用的動做。cookie

1.4 關鍵字

call subroutine, return(action),new,set,unset

2. 內置的Subroutines

內置函數4.0

Varnish 處理 client 的請求和後端服務器的響應時,會調用多個內置的 subroutines 進行處理。經過 CLI 執行 vcl.load 和 vcl.discard 時,也會調用內置的 subroutines。ide

下面對前端(client-side)和後端(backend-side)的處理分別進行介紹:

2.1 client-side

vcl_recv

在請求開始時調用,在接收並解析完整的請求以後調用,在從新啓動以後調用,或者做爲ESI include的結果調用。
它的目的是決定是否爲請求服務,可能會修改它,並決定如何進一步處理它。能夠將後端提示設置爲後端處理端默認設置。

vcl_recv 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

hash
    請求的對象被認爲是一個可能被緩存的對象,將繼續對其進行處理。將控制權轉交給 vcl_hash 子例程。

pass
    轉換至 pass 模式。控制權最終交給 vcl_pass 子例程。

pipe
    轉換至 pipe 模式。控制權最終交給 vcl_pipe 子例程。

synth(status code, reason)
    轉移到 vcl_synth 子例程,synth() 的參數值被預置爲 resp.status 和 resp.reason

purge
    清除請求的對象,以及它的變量(variants)。控制權先交給 vcl_hash,最終交給 vcl_purge

vcl_pipe

進入 pipe 模式時,vcl_pipe 子例程將被調用。在這個模式中,請求將被傳遞給後端服務器,這時 Varnish 會降級成爲一個 TCP 代理,只充當一個數據流的通道,不會對數據進行任何修改,當 client 或 server 端決定關閉鏈接時,該模式結束。在調用 vcl_pipe 以後,對於一個處於 pipe 模式的鏈接,其餘任何的 VCL 子例程都不會被調用。

vcl_pipe 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

pipe
    繼續以 pipe mode 運行

synth(status code, reason)
    轉移到 vcl_synth 子例程,synth() 的參數值被預置爲 resp.status 和 resp.reason

vcl_pass

在進入 pass 模式時,vcl_pass 將被調用,請求被轉發給後端服務器,後端服務器的響應被轉發給 client,可是響應不會被緩存。來自該 client 鏈接的後續請求,將被正常處理。

vcl_pass 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

fetch
    繼續以 pass mode 運行 - 發起一個對後端服務器的請求

restart
    重啓該 transaction。增長 restart 計數器的計數。若是計數超過了 max_restarts,Varnish 發出一個錯誤:guru meditation error.

synth(status code, reason)
    轉移到 vcl_synth 子例程,synth() 的參數值被預置爲 resp.status 和 resp.reason

vcl_hit

當緩存查找成功,vcl_hit 將被調用。緩存對象可能會過時,其 ttl 可能爲 0 或者負數,with only grace or keep time left.

vcl_hit 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

deliver
    發送該對象。若是該對象過時,將觸發一個 fetch 調用,更新該對象。

fetch
    儘管緩存命中,可是會同步地從後端服務器更新緩存對象。控制權最終轉交給 vcl_miss。

pass
    轉換至 pass 模式。控制權最終交給 vcl_pass 子例程。

restart
    重啓該 transaction。增長 restart 計數器的計數。若是計數超過了 max_restarts,Varnish 發出一個錯誤:guru meditation error.

synth(status code, reason)
    轉移到 vcl_synth 子例程,synth() 的參數值被預置爲 resp.status 和 resp.reason

vcl_miss

當緩存查找失敗,或者當 vcl_hit 返回一個 fetch 時,調用 vcl_miss。
vcl_miss 用於決定是否嘗試從後端服務器獲取文件。

vcl_miss 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

fetch
    從後端服務器獲取請求的對象。控制權最終轉交給 vcl_backend_fetch。

pass
    轉換至 pass 模式。控制權最終交給 vcl_pass 子例程。

restart
    重啓該 transaction。增長 restart 計數器的計數。若是計數超過了 max_restarts,Varnish 發出一個錯誤:guru meditation error.

synth(status code, reason)
    轉移到 vcl_synth 子例程,synth() 的參數值被預置爲 resp.status 和 resp.reason

vcl_hash

當 vcl_recv 爲請求建立了一個 hash 值時被調用。使用該值做爲 key 進行緩存查找。

vcl_hash 子例程只能以 return(lookup) 終止:

lookup
    在緩存中查找請求的對象。若是從 vcl_recv 返回 return(purge),控制權轉交給 vcl_purge。
    不然,若是緩存查找的結果是 hit,控制權轉交給 vcl_hit;若是緩存查找的結果是 miss,控制權轉交給 vcl_miss;
    若是緩存查找的結果是 hit on a hit-for-pass 對象 (object with obj.uncacheable == true),控制權轉交給 vcl_pass。

vcl_purge

執行 purge 以後,vcl_purge 被調用,緩存對象被清除(失效),其全部變量(variants)將被迴避。

vcl_purge 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

restart
    重啓該 transaction。增長 restart 計數器的計數。若是計數超過了 max_restarts,Varnish 發出一個錯誤:guru meditation error.

synth(status code, reason)
    轉移到 vcl_synth 子例程,synth() 的參數值被預置爲 resp.status 和 resp.reason

vcl_deliver

發送對象給客戶端前調用,除了將一個 vcl_synth 結果發送給客戶端時不會調用。

vcl_deliver 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

deliver
    發送對象給 client

restart
    重啓該 transaction。增長 restart 計數器的計數。若是計數超過了 max_restarts,Varnish 發出一個錯誤:guru meditation error.

synth(status code, reason)
    轉移到 vcl_synth 子例程,synth() 的參數值被預置爲 resp.status 和 resp.reason

vcl_synth

調用 vcl_synth 能夠發送一個 synthetic 對象給客戶端。synthetic 對象由 VCL 生成,不是從後端獲取的。可以使用 synthetic() 函數構造 synthetic 對象。

vcl_synth 定義了一個對象,該對象不會被緩存,與其相反,vcl_backend_error 所定義的對象可能最終被緩存。

vcl_synth 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

deliver
    直接將 vcl_synth 定義的對象發送給客戶端,不調用 vcl_deliver

restart
    重啓該 transaction。增長 restart 計數器的計數。若是計數超過了 max_restarts,
    Varnish 發出一個錯誤:guru meditation error.

2.2 backend-side

vcl_backend_fetch(more)

對後端服務器發送請求時調用 vcl_backend_fetch。在這個子例程中,咱們通常會修改請求,而後才發送給後端服務器。

vcl_backend_fetch 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

fetch
    從後端服務器獲取對象

abandon
    放棄對後端發起請求。除非後端請求是一個 background fetch,不然控制權將被轉交給 client-side 的 vcl_synth,
    其 resp.status 被設置爲 503。

vcl_backend_response

當成功從後端服務器獲取到 response headers 時,調用 vcl_backend_response。

vcl_backend_response 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

deliver
    對於一個 304 響應,建立一個更新的緩存對象。不然,從後端獲取對象的 body,而後發起 delevery 返回給客戶端。
    極可能是並行的(streaming)

abandon
    放棄對後端發起請求。除非後端請求是一個 background fetch,不然控制權將被轉交給 client-side 的 vcl_synth,
    其 resp.status 被設置爲 503。
        
retry
    重試發起 backend transaction。增長重試計數,若是重試次數超過 max_retries,控制權轉交給 vcl_backend_error

vcl_backend_error

當嘗試從後端獲取對象失敗,或則重試次數超過 max_retries 時,vcl_backend_error 將被調用。

VCL 生成一個 synthetic 對象,可以使用 synthetic() 函數構造 synthetic 對象的 body。

vcl_backend_error 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

deliver
    發送 vcl_backend_error 定義的對象,可能的話,緩存該對象。就如同該對象是從後端獲取的通常。這也被稱爲 "backend synth"。

retry
    重試發起 backend transaction。增長重試計數,若是重試次數超過 max_retries,調用 client-side 的 vcl_synth,
    其 resp.status 被設置爲 503。

2.3 vcl.load / vcl.discard

vcl_init

當加載 VCL 以後,vcl_init 被調用。通常用於初始化 VMODs。

vcl_init 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

ok
    正常返回,VCL 繼續加載

fail
    中止加載這個 VCL

vcl_fini

當一個 VCL 被廢棄,當該 VCL 處理完全部請求,調用 vcl_fini。通常用於清除 VMODs。

vcl_fini 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:

ok
    正常返回,VCL 將被廢棄。

3. Request and response VCL objects

VCL中有些須要你注意的重要對象。這些對象能夠在VCL被使用和操做

---req
請求對象。當vanish接收到請求後,req對象被建立和生成。你能夠在vcl_recv中使用req對象作不少事。

---bereq
The backend request object. Varnish contructs this before sending it to the backend. It is based on the req object.
後端請求對象。varnish在發送請求到後端以前構建這個對象。它基於req對象。

---beresp
後端響應對象。它包含在從後端響應對象的頭裏。若是你想修改後端server返回的響應信息,你能夠在vcl_backend_response中修改beresp對象。

---resp
傳遞給客戶端響應以前的response對象。一般在vcl_deliver中修改。

---obj
The object as it is stored in cache. Read only.
存儲在緩存中的對象。 只讀。

4. action:return(action)

actions 是在終止一個內置子例程時,配合 return() 使用的,如 return(pass),最經常使用的 actions 是這些:

---pass
當你在子程序中return(pass)請求和隨後的響應將被傳遞到後端server和從後端server回傳回來。響應將不會被緩存。pass能夠從vcl_recv中返回。

---hash
在*vcl_recv*中return(hash),通知varnish從cache查找請求內容,除非這個請求不被標示,那麼請求應當被pass。

---pipe .. XXX:What is pipe? benc
若是從 vcl_recv 返回 pipe,將會進入 pipe 模式,Varnish 將前端與客戶端的鏈接,以及與後端服務器的鏈接合併成一個數據流的通道,Varnish 不對數據作任何修改,只是將數據在兩端發送,因此你的日誌是不完整的。
pipe也能夠在*vcl_recv*中返回,return(pipe)。

---deliver
傳遞對象給客戶端。一般在vcl_backend_response中return。

---restart
Restart processing of the request. You can restart the processing of the whole transaction. Changes to the req object are retained.
從新對請求進行處理。你能夠在整個請求處理的階段重啓。更改過的req對象將被保留。

---retry
Retry the request against the backend. This can be returned from vcl_backend_response or vcl_backend_error if you don't like the response that the backend delivered .
重啓指向後端的請求。若是你不想從後端得到響應,你能夠在vcl_backend_response 或者vcl_backend_error 中return。

5. 內建函數

hash_data():指明哈希計算的數據;減小差別,以提高命中率;
regsub(str,regex,sub):把str中被regex第一次匹配到字符串替換爲sub;主要用於URL Rewrite
regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替換爲sub;
return():當某VCL域運行結束時將控制權返回給Varnish,並指示Varnish如何進行後續的動做;其能夠返回的指令包括:lookup、hash、hit、miss、pass、pipe、hit_for_pass、purge等;但某特定域可能僅能返回某些特定的指令,而非前面列出的所有指令;
return(restart):從新運行整個VCL,即從新從vcl_recv開始進行處理;每一次重啓都會增長req.restarts變量中的值,而max_restarts參數則用於限定最大重啓次數。
ban(expression):清除能被表達式匹配的全部緩存對象
ban_url(regex):Bans全部的其URL能夠被此處的regex匹配到的緩存對象;
synth(status,"STRING"):purge操做;


6. 變量

內建變量

req.*:request,表示由客戶端發來的請求報文相關;
    req.http.* *能夠是http請求報文的任意首部的名稱,表明引用http的某個請求首部
        req.http.User-Agent, req.http.Referer, ...
        req.http.host
    req.method 表示客戶端的請求方法
    req.url 表示客戶端請求的url

bereq.*:varnish主機在向後端真實服務器發送http請求報文時的相關變量。
    如:能夠將真實的客戶端地址傳遞給後端真實web服務器,以便於後端真實服務器記錄客戶端的真實IP,而不是varnish的IP
    bereq.http.* 表明varnish發日後端的真實的web服務器的相關的請求報文中的首部

beresp.*:由後端真實服務器發來的http響應報文中的某些首部信息相關的變量,通常是在vcl_backend_response或vcl_backend_fenth引擎中調用
    beresp.http.*
resp.*:由varnish響應給客戶端的響應報文相關的變量;
    通常用在vcl_deliver引擎中進行調用,由於deliver引擎是用於給客戶端構建響應報文,發送響應報文  
    resp.http.: 能夠是響應報文中的任意首部的名稱,表明引用某個響應報文的值,可用於設定、添加、修改響應給客戶端的響應報文中的響應首部的值

obj.*:對存儲在緩存空間中的緩存對象屬性的引用變量;只讀;
    obj.hits: 某個緩存對象的緩存的命中次數

client.,server.,storage.*:可用在全部面向客戶端一側的引擎中,也就是vcl_recv、vcl_pipe、vcl_hash、vcl_pass、vcl_purge、vcl_miss、vcl_hit、vcl_deliver、vcl_synth中:
    client.ip 表明客戶端的IP地址
    server.ip 表明當前varnish的IP地址
    client.port 表明客戶端的端口
    server.port 表明當前varnish的端口

用戶自定義變量
    可用set,來設定某個用戶自定義變量或現有變量的值
    可用unset,來取消某個用戶自定義變量,或刪除現有變量

經常使用內建變量說明

  • bereq.*
    bereq.http.HEADERS: 表示varnish發日後端真實web服務器的請求報文中的某個首部
    bereq.request: 表示varnish發日後端真實web服務器的請求報文的請求方法(4.0版本的varnish改成了bereq.method)
    bereq.url:表示varnish發日後端真實web服務器的請求報文的請求的url
    bereq.proto:表示varnish發日後端真實web服務器的請求報文的http協議的協議版本
    bereq.backend:表示要varnish發送請求到後端真實web服務器時,後端服務器不止一臺時,所調用的後端主機

  • beresp.*
    beresp.http.HEADERS:表示後端真實web服務器發給varnish的http響應報文的某個首部的信息
    beresp.proto:表示後端真實web服務器發給varnish的http響應報文的http協議版本
    beresp.status:表示後端真實web服務器發給varnish的http響應報文的響應狀態碼
    beresp.backend.name:表示後端真實web服務器發給varnish的http響應報文的後端主機的名稱
    beresp.ttl:後端服務器響應中的內容的餘下的生存時長

  • obj.*
    obj.hit 此對象在緩存中命中的次數
    obj.ttl 此對象的ttl值,也就是其緩存時長

  • server.*
    server.ip 當前varnish的IP
    server.hostname 當前varnish的主機名

  • req.*
    req.http.HEADERS: 表示客戶端發送給varnish的請求報文中的某個首部
    req.request: 表示客戶端發送給varnish的請求報文的請求方法(4.0版本的varnish改成了req.method)
    req.url:表示客戶端發送給varnish的請求報文的請求的url
    req.proto:表示客戶端發送給varnish的請求報文的http協議的協議版本

  • resp.*
    resp.http.HEADERS:表示varnish發送給客戶端的響應報文的某個首部的信息
    resp.proto:表示varnish發送給客戶端的http響應報文的http協議版本
    resp.status:表示varnish發送給客戶端的http響應報文的響應狀態碼

  • 自定義變量:可用set 變量名= 值 來設定變量。例:
    set resp.http.X-Cache = "HIT"
    表示設定響應給客戶端的響應報文中設定X-Cache首部的值爲HIT
    set resp.http.IS-Cache = "YES"+" "server.ip
    表示設定響應給客戶端的響應報文中的IS-Cache首部的值爲"YES
    varnish服務器IP",多個元素之間要用+加號鏈接,若是要輸出空格,須要用""引號引發來

  • 取消某變量:用unset 變量名。例:
    unset req.http.cookie
    表示取消客戶端請求報文中http的cookie首部信息
    unset beresp.http.Set-cookie
    表示取消後端服務器發送到varnish上的響應報文http首部中的Set-cookie首部

同時注意變量是受狀態限制的,下圖爲可用表:


  [sleepy↓]

相關文章
相關標籤/搜索