在VCL中,有3個重要的數據結構:
1.req:請求目標,當varnish接收到一個請求,這是req object就被創建了,在vcl_recv中的大部分工作,都是在req object上展開的。
2.beresp:後端服務器返回的目標,它包含返回的頭信息,在vcl_fetch中的大部分工作都是在beresp onject上開展的。
3.obj:被cache的目標,只讀的目標被保存於內存中,obj.ttl的值可以修改,其他的只能讀
由於子程序沒有參數,子進程必須的信息通過全局變量來處理。
以下是到處都可用的變量:
- now:當前時間
下面的變量在backend申明中有效: - .host:一個backend的主機名或者IP地址
- .port:一個backend的服務名字或者端口號
下面的變量在處理請求時有效: - cient.ip:客戶端IP
- cient.identity:客戶的id,用在負載均衡的時候的client director
- server.hostname:server的主機名
- server.identity:server的身份,使用-i參數設置,如果-i參數沒有傳遞給varnishd,server.identity將給varnishd實例設置名字。
- server.ip:客戶端連接上socket,接收到的IP地址
- server.port:客戶端連接上socket,接收到的端口號
- req.request:請求類型,例如“GET”,“HEAD”
- req.proto:客戶端的HTTP協議
- req.url:請求的URL
- req.backend:使用哪個後端服務器爲這個請求提供服務
- req.backend.healthy:後端服務器是否健康
- req.http.具體header名字:對應的HTTP頭,如req.http.Cookie
- req.hash_always_miss:強制本請求的緩存失效
- req.hash_ignore_busy:當lookup緩存時,忽略busy的對象
- req.can_gzip:設置能使用gzip
- req.restarts:設置最大的重啓次數
- req.esi:設置是否支持ESI,今後會改變,建議不要使用
- req.esi_level:設置ESI的level
- req.grace:設置對象被保持的時間
- req.xid:請求的唯一id
下面這些變量在訪問後端服務器的時候用
- bereq.request:請求的類型(如“GET”,“HEAD”)
- bereq.url:請求的url
- bereq.proto:請求的協議
- bereq.http.具體header名字:請求的HTTP頭,如bereq.http.Cookie
- bereq.connect_timeout:等待後端服務器響應的時間
- bereq.first_byte_timeout:等待接受第一個字節的等待時間,pipe模式中無效
- bereq.between_bytes_timeout:兩次從後端服務器接收到的字節的間隔,pipe模式無效
下面這些變量在從後端服務器取回,但還沒有進入緩存的時候使用,也就是vcl_fetch變量
- beresp.do_stream:對象直接返回給客戶端,不會再varnish中緩存。在Varnish3裏面這些對象會被標記爲busy
- beresp.do_esi:是否進行ESI處理
- beresp.do_gzip:是否存儲前Gzip壓縮
- beresp.do_gunzip:是否在存儲前解壓縮
- beresp.http.具體header名字:HTTP頭部,如bereq.http.Cookie
- beresp.proto:HTTP協議
- beresp.status:HTTP的狀態碼
- beresp.response:服務端返回的狀態消息
- beresp.ttl:對象保存的時間
- beresp.grace:對象grace保存的時間
- beresp.saintmode:saint模式持續的時間
- beresp.backend.name:response的backend的名字
- beresp.backend.ip:response的backend的ip
- beresp.backend.port:response的backend的端口
- beresp.storage:強制Varnish保存這個對象
下面這些變量在請求目標被成功的從後端服務器或者緩存中獲得後有效
- obj.proto:返回請求目標的HTTP版本
- obj.status :服務器返回的HTTP狀態碼
- obj.response :服務器返回的HTTP狀態信息
- obj.ttl:目標的剩餘生存時間,以秒爲單位。
- obj.lastuse:最後一個請求後,過去的時間,以秒爲單位。
- obj.hits:大概的delivered的次數,如果爲0,表明緩存出錯。
- obj.grace:對象grace的存活時間
- obj.http.具體header的名字:Http header
下面這些變量在目標hash key以後有效
- req.hash:hashkey 和緩存中的目標相關,在讀出和寫入緩存時使用。
- 下面這些變量在準備迴應客戶端時使用
- resp.proto:準備響應的HTTP協議版本
- resp.status:返回客戶端的HTTP狀態碼
- resp.response:返回客戶端的HTTP狀態信息
- resp.http.header:通信的HTTP頭
使用SET關鍵字,把值分配給變量:
sub vcl_recv {
# Normalize the Host: header
if (req.http.host ~ "^(www.)?example.com$") {
set req.http.host = "www.example.com";
}
}
可以使用remove關鍵字把HTTP頭徹底的刪除:
sub vcl_fetch {
remove obj.http.Set-Cookie;
}
常見VCL應用片段
1.爲不同的設備設置不同的header參數:
sub vcl_recv {
if (req.http.User-Agent ~ "iPad" ||
req.http.User-Agent ~ "iPhone" ||
req.http.User-Agent ~ "Android") {
set req.http.X-Device = "mobile";
} else {
set req.http.X-Device = "desktop";
}
}
2.想要取消訪問/images的request的cookie:
sub vcl_recv {
if (req.url ~ "^/images") {
unset req.http.cookie;
}
}
3.通過ACL來控制能訪問的ip地址
acl local {
"localhost";
"192.168.1.0"/24; /* and everyone on the local network */
! "192.168.1.23"; /* except for the dialin router */
}
sub vcl_recv {
if (req.request == "PURGE") {
if (client.ip ~ local) {
return(lookup);
}
}
}
sub vcl_hit {
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
error 404 "Not in cache.";
}
}
4.修改從後臺服務器返回的對象的ttl:
sub vcl_fetch {
if (req.url ~ "\.(png|gif|jpg)$") {
unset beresp.http.set-cookie;
set beresp.ttl = 1h;
}
}
5.設置客戶端發送的accept-encoding頭只有gzip和deflate兩種編碼,gzip優先
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
# No point in compressing these
remove req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
# unknown algorithm
remove req.http.Accept-Encoding;
}
}
6.簡單的圖片防盜鏈:
if (req.http.referer ~ "http://.*") {
if ( !(req.http.referer ~ "http://.*baidu\.com"
|| req.http.referer ~ "http://.*google\.com"
|| req.http.referer ~ "http://.*google\.cn"
)) {
set req.http.host = "www.baidu.com";
set req.url = "/static/images/logo.gif";
}
return (lookup);
}