varnish緩存服務器是工做在代理模式的。意思是說,由varnish接收用戶的請求,把用戶請求資源的URL作「哈唏」編碼後,作爲「鍵」與緩存條目中的鍵作比對:html
一、若是,緩存條目有如出一轍的鍵的話,那麼該鍵對應的值就是用戶請求URL對應的資源,vim
varnish把該鍵對應的值取出來,響應給客戶端。後端
二、若是,緩存條目沒有與之匹配的鍵的話,那麼varnish 就向後端服務器(backup server)發送緩存
請求。當後端服務器(backup server )構建完響應報文響應varnish,varnish服務器收到後端安全
服務器(backup server)的響應後,會把:用戶請求的URL作「哈唏」編碼後,bash
做爲鍵(key),該URL對應的資源做爲值(value),保存在varnish的緩存中。服務器
這就是所謂的,插入緩存條目。 varnish的緩存條目是:key:value 方式存在的。curl
而後,varnish再構建響應報文響應客戶端。tcp
這就是,varnish 緩存服務器的正常工做流程。ide
以下圖所示:
那麼如何實現varnish緩存的管理呢?
一、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 ~ "/p_w_picpaths/a.jpg$" ) { return (pass); } return (lookup); }
二、當緩存沒有命中(cache miss)如何控制 varnish 向緩存中插入緩存條目時,該緩存條目的過時時長呢?
使用 varnish 緩存服務器提供的:vcl_fetch 狀態引擎來控制是否向緩存中插入緩存條目的。
如:
sub vcl_recv { .... if (req.request == "GET" && req.request ~ "\.png$") { set beresp.ttl = 10s; } .... }
三、如何修剪(刪除)緩存條目呢?
使用 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
說明:
四、定義緩存大小;
[root@haproxy2 ~]# vim /etc/sysconfig/varnish VARNISH_STORAGE_SIZE=64M ----> 定義緩存大小 VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}" ---> 明確指定varnish使用內存作爲緩存。