varnish緩存服務器是工作在代理模式的。意思是說,由varnish接收用戶的請求,把用戶請求資源的URL做“哈唏”編碼後,做爲“鍵”與緩存條目中的鍵做比對:
1、如果,緩存條目有一模一樣的鍵的話,那麼該鍵對應的值就是用戶請求URL對應的資源,
varnish把該鍵對應的值取出來,響應給客戶端。
2、如果,緩存條目沒有與之匹配的鍵的話,那麼varnish 就向後端服務器(backup server)發送
請求。當後端服務器(backup server )構建完響應報文響應varnish,varnish服務器收到後端
服務器(backup server)的響應後,會把:用戶請求的URL做“哈唏”編碼後,
作爲鍵(key),該URL對應的資源作爲值(value),保存在varnish的緩存中。
這就是所謂的,插入緩存條目。 varnish的緩存條目是:key:value 方式存在的。
然後,varnish再構建響應報文響應客戶端。
這就是,varnish 緩存服務器的正常工作流程。
如下圖所示:
那麼如何實現varnish緩存的管理呢?
1、varnish接收用戶請求後,是如何根據用戶請求的報文來決定是否查找緩存的呢?
由上圖所知。當 varnish 服務器接收到用戶請求後,分析用戶請求的 URL 是否符合緩存標準,再查找緩存。這樣是爲了避免花費在與緩存條目比對的時間。如果,緩存條目較多的話,做緩存比對也是需要很長時間的。varnish通過如下方式,控制那些URL可以查找緩存的:
varnish 在vcl_recv狀態引擎定義策略,怎麼樣處理用戶的請求的。如:varnish 處理的客戶端請求的標準、如果判斷是否查找緩存的。
sub vcl_recv { # varnish 在vcl_recv狀態引擎定義的策略來控制,varnish服務器只處理指定http協議請求資源的方法,的URL if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" &&\ req.request != "OPTIONS" && req.request != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); -----> 用戶請求的訪問的服務雖然是:tcp/80 但是,varnish不處理除了,GET、HEAD、PUT、POST、TRACE、OPTIONS、DELETE請求資源的方法。直接讓該請求把該請求交給backup server. } # 再使用下述策略來過濾用戶請求資源時所使用的方法;判斷用戶請求資源時使用的方法不是:GET、HEAD 就繞過查找緩存的操作 if (req.request != "GET" && req.request != "HEAD") { /* We only deal with GET and HEAD by default */ return (pass); -----> 繞過查找緩存操作,varnish直接向 backup server 請求資源 } # 使用vcl_recv狀態引擎判斷用戶的請求,都不符合上述:if 條件。那麼該用戶請求資源所使用的方法一定是:GET或HEAD。但是如果用戶訪問的是資源,需要通過口令認證 # 纔可以訪問的。用戶請求該資源使用的也是"GET"方法。該用戶請求的URL是不需要查找緩存的。 if (req.http.Authorization || req.http.Cookie) { /* Not cacheable by default */ return (pass); -----> 繞過查找緩存操作,varnish直接向 backup server 請求資源 } return (lookup); ------> 查找緩存 }
說明:
varnish 有很多內置變量保存了,http協議報文的信息。通過使用if判斷這些信息,來控制varnish是如何使用緩存的。
如:
req.url ------> 記錄用戶請求的URL req.request -------> 記錄了用戶請求資源使用的方法 req.http.HEADER -------> 記錄了用戶請求報文的首部。該變量是可寫的。如:req.http.hostreq.restarts -------> 請求被重啓的次數 server.ip -------> varnish 的IP地址 server.port -------> varnish 監聽的端口 server.hostname -------> 服務器的主機名 client.ip -------> 客戶端IP req.backend -------> 如果,未從緩存中命中。該請求分調度到後端的那個服務器。
例:
當用戶訪問指定頁面時,禁止查詢緩存
sub vcl_recv { ... if (req.url ~ "/images/a.jpg$" ) { return (pass); } return (lookup); }
2、當緩存沒有命中(cache miss)如何控制 varnish 向緩存中插入緩存條目時,該緩存條目的過期時長呢?
使用 varnish 緩存服務器提供的:vcl_fetch 狀態引擎來控制是否向緩存中插入緩存條目的。
如:
sub vcl_recv { .... if (req.request == "GET" && req.request ~ "\.png$") { set beresp.ttl = 10s; } .... }
3、如何修剪(刪除)緩存條目呢?
使用 varnish 提供 purge指令來清除不需要的緩存
如:
(1)、爲了安全,對操作清除緩存條目的指令的用戶做限制
只允許下述用戶修剪緩存條目
acl purgers { "127.0.0.1"; "172.16.13.0"/24; }
(2)、在vcl_recv 狀態引擎,放行purge請求方法查詢緩存
sub vcl_recv { 。。。 if (req.request == "PURGE") { ----------> 開放用戶請求資源使用 purgers 方法, if ( client.ip !~ purgers ) { ------> 檢測發起 PURGE 方法的用戶來源,只允許屬於purgers的用戶的請求查詢緩存 error 405 "Method not allowed"; } return (lookup); --------> 查詢緩存 } }
(3)、當緩存命中(cache hit)就執行varnish 的purge清除(修剪)緩存條目的指令
sub vcl_hit { if (req.request == "PURGE") { purge; ----------> 執行varnish 修改緩存的指令 error 200 "Purged"; ----> 合成狀態碼,和“原因短語” } return (deliver); }
(4)、使用【curl】指定使用PURGE方法訪問指定的資源,實現緩存修剪
如:
curl -X PURGE http://172.16.13.1/index.html
說明:
4、定義緩存大小;
[root@haproxy2 ~]# vim /etc/sysconfig/varnish VARNISH_STORAGE_SIZE=64M ----> 定義緩存大小 VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}" ---> 明確指定varnish使用內存做爲緩存。