Varnish Cache是一個web應用程序加速器,也是一個HTTP反向代理軟件。放在HTTP服務器前端,css
緩存內容。它採用「Visual Page Cache"技術,全部緩存數據直接從內存讀取,所以速度很是快。html
VCL4相比VCL3語法的改變點前端
要在配置文件中指定版本:即在第一行寫上 vcl 4.0;web
vcl_fetch函數被vcl_backend_response代替,且req.*再也不適用vcl_backend_response;後端
後端源服務器組director成爲varnish模塊,需import directors後再在vcl_init子例程中定義;緩存
vcl_error變動爲vcl_backend_error,必須使用beresp.*,而不是obj.*。bash
req.request變動爲req.method,obj爲只讀對象了。服務器
自定義的子例程(即一個sub)不能以vcl_開頭,調用使用call sub_name;cookie
error()函數被synth()替代;ide
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.* 。
更詳細改變,請查看官方文檔。
https://www.varnish-cache.org/docs/4.0/whats-new/upgrading.html
VCL內置函數
vcl_recv 在一個請求到達時調用,它的決定是否處理此請求,以及如何處理。可以使用如下幾個終止語句:
synth(狀態碼,緣由)
pass:繞過緩存,不從緩存中查詢內容也不講內容存至緩存中
pipe:不對客戶端進行檢查或作出任何操做,經過管道直接送日後方服務器,將數據直接經過管道在二者間傳送
purge 清除此對象
hash 在緩存中查找用戶請求的對象,若是緩存中沒有其請求的對象,後續操做極可能會將其請求的對象進行緩存;
vcl_pipe 此函數在進入pipe模式時被調用,用於將請求直接傳遞至後端主機,並將後端響應原樣返回客戶端;
synth(satus code,reason)
pipe
vcl_pass 此函數在進入pass模式時被調用,用於將請求直接傳遞至後端主機,但後端主機的響應並不緩存直接返回客戶端;
synth(status code,reason)
fetch 表示從後端獲取請求的內容,並把控制權交給vcl_fetch函數。
restart 重啓整個VCL,並增長重啓計數;超出max_restarts限定的最大重啓次數後將會返回錯誤信息;
vcl_hit 在執行 lookup 指令後,在緩存中找到請求的內容後將自動調用該函數;
restart
deliver 緩存此對象,並將其發送給客戶端(經由vcl_deliver);
synth(status code,reason)
vcl_miss 在執行 lookup 指令後,在緩存中沒有找到請求的內容時自動調用該方法,此函數可用於判斷是否須要從後端服務器獲取內容;
synth(status code,reason)
pass
fetch
restart
vcl_hash 在vcl_recv調用後爲請求建立一個hash值時,調用此函數;此hash值將做爲varnish中搜索緩存對象的key;
lookup 在緩存中查找用戶請求的對象,並把控制權交給vcl_miss,vcl_hit或者vcl_purge
vcl_purge pruge操做執行後調用此函數,可用於構建一個響應;
synth
restart
vcl_deliver 將在緩存中找到請求的內容發送給客戶端前調用此方法;
deliver
restart
vcl_backend_fetch 向後端主機發送請求前,調用此函數,可修改發日後端的請求;
fetch
abandon 放棄後端的請求,並生成一個錯誤
vcl_backend_response 得到後端主機的響應後,可調用此函數;
deliver
abandon
retry
vcl_backend_error 當從後端主機獲取源文件失敗時,調用此函數;
deliver
retry
vcl_synth
deliver
restart
vcl_init VCL加載時調用此函數,常常用於初始化varnish模塊(VMODs)
ok 正常返回,VCL繼續工做
vcl_fini 當全部請求都離開當前VCL,且當前VCL被棄用時,調用此函數,常常用於清理varnish模塊;
ok
變量類型:
req:The request object,請求到達時可用的變量
bereq:The backend request object,向後端主機請求時可用的變量
beresp:The backend response object,從後端主機獲取內容時可用的變量
resp:The HTTP response object,對客戶端響應時可用的變量
obj:存儲在內存中時對象屬性相關的可用的變量
案例分析:
vcl 4.0; probe backend_healthcheck { #健康情況監測 .url = "/health.html"; .timeout = 1s; .interval = 10s; .window = 5; .threshold = 2; } backend web2 { #建立後端主機 .host = "192.168.1.139"; .port = "80"; .probe = backend_healthcheck; } backend p_w_picpath1 { .host = "192.168.1.140"; .port = "80"; .probe = backend_healthcheck; } backend p_w_picpath2 { .host = "192.168.1.141"; .port = "80"; .probe = backend_healthcheck; } backend web1 { .host = "192.168.1.138"; .port = "80"; .probe = backend_healthcheck; } import directors; sub vcl_init { #建立後端主機組,基於round_robin輪轉 new web_cluster = directors.round_robin(); web_cluster.add_backend(web1); web_cluster.add_backend(web2); new img_cluster = directors.round_robin(); img_cluster.add_backend(p_w_picpath1); img_cluster.add_backend(p_w_picpath2); } acl purgers { #定義PURGE方法訪問來源IP "localhost"; "127.0.0.1"; "192.168.1.0"/24; } sub vcl_recv { if (req.method == "GET" && req.http.Cookie) { #緩存帶cookie的GET請求 return(hash); } if (req.url ~ "test.html") { #測試頁面不緩存 return(pass); } if (req.method == "PURGE") { #當發送PURGE請求的客戶端再也不acl中指定地址時,返回405狀態代碼,並提示Not allowed. if (!client.ip ~ purgers) { return(synth(405,"Not allowed")); } return(hash); } if (req.http.X-Forward-For) { #爲後端主機添加X-Forward-For首部 set req.http.X-Forward-For = req.http.X-Forward-For + "," +client.ip; } else { set req.http.X-Forward-For = client.ip; } if (req.http.host ~ "^(www.|bbs.)?mingxiao.info") { #域名訪問策略 set req.backend_hint = web_cluster.backend(); } if (req.http.host ~ "^(img.|p_w_picpaths.)?mingxiao.info") { set req.backend_hint = img_cluster.backend(); } return(hash); } sub vcl_hit { #若是請求的是PURGE方法,命中的話返回200狀態碼。 if (req.method == "PURGE") { return(synth(200,"Purged")); } } sub vcl_miss { if (req.method == "PURGE") { return(synth(404,"Not in cache")); } } sub vcl_pass { if (req.method == "PURGE") { return(synth(502,"PURGE on a passed object")); } } sub vcl_backend_response { if (bereq.url ~ "\.(jpg|jpeg|gif|png)$") { set beresp.ttl = 6000s; } if (bereq.url ~ "\.(html|css|js)$") { set beresp.ttl = 6000s; } if (beresp.http.Set-Cookie) { return(deliver); } } sub vcl_deliver { if (obj.hits >0) { set resp.http.X-Cache="Hit from"+" "+server.ip; } else { set resp.http.X-Cache="Miss from"+" "+server.ip; } }