目錄html
知識來源爲官方文檔:
《Varnish用戶指南》
《Varnish4.0電子書》前端
經過對varnish原理的學習,咱們知道varnish緩存策略是基於VCL語言實現,處理邏輯是編寫在.vcl
配置文件中。
涉及的總要知識點有如下幾個:web
varnish 4.0版本開始,vcl擁有本身的默認規則,它不可移除,老是追加在自定義的規則以後。正則表達式
//
or#
or/* foo */
;VCL4相比VCL3語法的改變點:express
sub subroutine { ... }
if CONDITION { ... } else { ... }
return() # Functions hash_data() # Functions
= 賦值 == 等於 ~ 匹配,能夠與正則表達式或ACL一塊兒使用。同時注意匹配的規則若是是字符串,則須要 " " 引發。 ! 邏輯非 && 邏輯與 || 邏輯或
子例程:
子例程用於對代碼進行分組以提升可讀性或可重用性,例:後端
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
call subroutine, return(action),new,set,unset
Varnish 處理 client 的請求和後端服務器的響應時,會調用多個內置的 subroutines 進行處理。經過 CLI 執行 vcl.load 和 vcl.discard 時,也會調用內置的 subroutines。ide
下面對前端(client-side)和後端(backend-side)的處理分別進行介紹:
在請求開始時調用,在接收並解析完整的請求以後調用,在從新啓動以後調用,或者做爲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
進入 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
在進入 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 將被調用。緩存對象可能會過時,其 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_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_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。
執行 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_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 能夠發送一個 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.
對後端服務器發送請求時調用 vcl_backend_fetch。在這個子例程中,咱們通常會修改請求,而後才發送給後端服務器。
vcl_backend_fetch 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:
fetch 從後端服務器獲取對象 abandon 放棄對後端發起請求。除非後端請求是一個 background fetch,不然控制權將被轉交給 client-side 的 vcl_synth, 其 resp.status 被設置爲 503。
當成功從後端服務器獲取到 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
當嘗試從後端獲取對象失敗,或則重試次數超過 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。
當加載 VCL 以後,vcl_init 被調用。通常用於初始化 VMODs。
vcl_init 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:
ok 正常返回,VCL 繼續加載 fail 中止加載這個 VCL
當一個 VCL 被廢棄,當該 VCL 處理完全部請求,調用 vcl_fini。通常用於清除 VMODs。
vcl_fini 子例程可以使用 return() 結合下面的其中一個關鍵字進行終止:
ok 正常返回,VCL 將被廢棄。
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. 存儲在緩存中的對象。 只讀。
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。
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操做;
↓
內建變量:
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↓]