WEB緩存系統之varnish緩存項修剪

  前文我們聊了下varnish的狀態引擎和不同類型的變量對應該使用在那個狀態引擎中,以及每個狀態引擎的對應處理事務;回顧請參考https://www.cnblogs.com/qiuhom-1874/p/12643549.html;今天我們來聊一聊varnish的緩存項修剪;

  什麼是緩存項修剪?所謂修剪我個人的理解是把多餘的部分或者不需要的部分刪除掉;對於varninsh來講,緩存項修剪也叫緩存項刪除;我們在varnish服務器上可以通過vcl語言來編寫緩存策略,對於某些緩存該如何緩存,緩存多久等等;假如我們在定義好緩存策略後,在定義緩存過期時間內,後端服務器內容發生了變化,或者後端服務器發生了內容更新,我們如果不把varnish上的緩存修剪掉,對於用戶來講,用戶的訪問就不是最新的數據;為了解決這樣的問題,我們需要人工手動的去修剪緩存項;而修剪緩存項一般都是針對某一類資源或特定資源來做修剪(通過用戶指定或正在匹配),一般不會也不應該是全部;在varnish中,修剪緩存的方式有兩種,一種是vcl_purge狀態引擎修剪(通過判斷用戶的某些請求首部特徵,來對用戶指定的資源進行修剪),一種是內部函數ban()來修剪緩存(通常在命令行執行ban命令修剪緩存);

  首先我們來看看varnish的默認配置中如何定義vcl_purge這個狀態引擎的;

[root@test_node1-centos7 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 "vcl.show -v boot"|grep -A3 purge  sub vcl_purge {      return (synth(200, "Purged"));  }    [root@test_node1-centos7 ~]#  

  提示:從上面默認配置中可以看到對於vcl_purge的配置很簡單;以上配置表示如果上一個狀態引擎把報文送給purge這個狀態引擎後,purge狀態引擎的操作就是把對應報文送給synth(),併合成一個200的響應碼,消息狀態是purged的合成頁面響應給客戶端;以上就是告訴客戶端緩存項修剪成功;

  了解了purge的處理機制後,我們在來看看緩存項的修剪應該在那個狀態引擎中定義;通常在接收到用戶請求後,就需要修剪緩存;這樣用戶才可以拿到最新頁面;所以我們在定義緩存的修剪操作應該在vcl_recv中定義;比如判斷用戶的請求方法,如果用戶請求的方法是我們自定義的請求方法,我們就把這類請求直接交給purge處理;

   提示:紅框中的內容就是來判斷用戶的請求方法,如果請求方法是“PURGE” 那麼就把對應的請求交給purge去處理;

  測試:用curl命令指定特定的請求方法去訪問varnish對外提供的頁面;通過判斷響應報文中,之前我們定義的X-Cache首部的值來判斷是否命中緩存;如果我們使用了purge方法後,第二次正常方式訪問應該是miss的,第三次訪問時hit就表示修剪緩存項成功;

[root@test_node1-centos7 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082  200  -----------------------------  Varnish Cache CLI 1.0  -----------------------------  Linux,3.10.0-693.el7.x86_64,x86_64,-sfile,-smalloc,-hcritbit  varnish-4.0.5 revision 07eff4c29    Type 'help' for command list.  Type 'quit' to close CLI session.      varnish> vcl.load test default.vcl  200  VCL compiled.    varnish> vcl.use test  200  VCL 'test' now active    varnish> quit  500  Closing CLI connection  [root@test_node1-centos7 ~]# curl  -I http://192.168.0.99:8000  HTTP/1.1 200 OK  Date: Thu, 09 Apr 2020 04:57:49 GMT  Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips  Strict-Transport-Security: max-age=31536000  Last-Modified: Tue, 31 Mar 2020 14:56:54 GMT  ETag: "2f-5a227c743121d"  Content-Length: 47  Content-Type: text/html; charset=UTF-8  X-Varnish: 65541  Age: 0  Via: 1.1 varnish-v4  X-Cache: miss via 192.168.0.99  Connection: keep-alive    [root@test_node1-centos7 ~]# curl  -I http://192.168.0.99:8000  HTTP/1.1 200 OK  Date: Thu, 09 Apr 2020 04:57:49 GMT  Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips  Strict-Transport-Security: max-age=31536000  Last-Modified: Tue, 31 Mar 2020 14:56:54 GMT  ETag: "2f-5a227c743121d"  Content-Length: 47  Content-Type: text/html; charset=UTF-8  X-Varnish: 32772 65542  Age: 3  Via: 1.1 varnish-v4  X-Cache: hit via 192.168.0.99  Connection: keep-alive    [root@test_node1-centos7 ~]# curl -X "PURGE" http://192.168.0.99:8000  <!DOCTYPE html>  <html>    <head>      <title>200 Purged</title>    </head>    <body>      <h1>Error 200 Purged</h1>      <p>Purged</p>      <h3>Guru Meditation:</h3>      <p>XID: 65544</p>      <hr>      <p>Varnish cache server</p>    </body>  </html>  [root@test_node1-centos7 ~]# curl  -I http://192.168.0.99:8000  HTTP/1.1 200 OK  Date: Thu, 09 Apr 2020 04:58:11 GMT  Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips  Strict-Transport-Security: max-age=31536000  Last-Modified: Tue, 31 Mar 2020 14:56:54 GMT  ETag: "2f-5a227c743121d"  Content-Length: 47  Content-Type: text/html; charset=UTF-8  X-Varnish: 32774  Age: 0  Via: 1.1 varnish-v4  X-Cache: miss via 192.168.0.99  Connection: keep-alive    [root@test_node1-centos7 ~]# curl  -I http://192.168.0.99:8000  HTTP/1.1 200 OK  Date: Thu, 09 Apr 2020 04:58:11 GMT  Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips  Strict-Transport-Security: max-age=31536000  Last-Modified: Tue, 31 Mar 2020 14:56:54 GMT  ETag: "2f-5a227c743121d"  Content-Length: 47  Content-Type: text/html; charset=UTF-8  X-Varnish: 32777 32775  Age: 3  Via: 1.1 varnish-v4  X-Cache: hit via 192.168.0.99  Connection: keep-alive    [root@test_node1-centos7 ~]#  

  提示:我們用purge方法去請求對應資源後,再用正常的get方法去獲取資源,對應響應報文首部X-Cache的值就變成miss的,說明沒用從緩存中命中;再次訪問X-Cache的值變成hit,說明從緩存中命中,這是因為第一次緩存修剪後,第二次訪問就把該資源緩存到varnish上,再次訪問varnish就直接從緩存中給我們響應;

  其實通過請求方法來判緩存項是否該修剪,其實很危險的;就以上面的配置,任何人都可以通過purge方法去修剪緩存,這很顯然是不能也不應該的;所以我們還需要限定那些用戶可以執行purge方法去修剪緩存;在varnish中添加訪問控制法則需要用acl關鍵指定,然後起一名稱,把對應的ip地址或網段地址寫進去;如下

   提示:以上就表示定義了一個訪問控制法則,其名稱叫做allow_purge_method_clients;其中這裏面寫ip地址需要用雙引號引起來,並用分號結束;對於網段地址掩碼位數需要寫在雙引號外;

  定義好訪問控制規則後,我們在原有的判斷用戶請求方法中加入限定IP地址的操作;

   提示:以上紅框中的內容表示如果用戶請求的方法是PURGE,IP地址不匹配我們指定的ip地址法則,那麼就返回合成403響應碼給客戶;如果匹配就執行purge操作;

  測試:用192.168.0.99這台主機用”PURGE”方法請求修剪和用192.168.0.22這台主機用”PURGE”方法修剪緩存,如果我們定義的緩存策略正確的話,第一台主機應該是可以修剪緩存的,第二台主機會提示不運行修剪緩存,響應403;

   提示:從上面的示例可以看到通過不同ip的主機對varnish發起“PURGE”方法修剪緩存,在自定義訪問控制法則中存在的IP就可以通過“PURGE”方法來修剪緩存,相反不再acl控制發展中的IP地址主機,就不被允許修剪緩存;

   以上是通過編寫vcl來判斷用戶的請求方法實現緩存修剪,除此之外varnish還支持內建命令ban來修剪緩存;接下來我們來看看用內建命名ban怎麼修剪緩存;

  首先我們可以來查看下ban命令的用法;

   提示:以上就是ban命令的用法,其中field表示用戶請求的某些首部,比如req.http.host、req.url等;operaror表示操作符 ,arg表示參數;

  示例:修剪用戶請求資源是index.html內容

   提示:以上紅框中的內容就相當於判斷用戶請求的url,如果匹配/index.html,就return(synth(200));意思就是說對用戶請求的/index.html的緩存項進行修剪(刪除);所以用戶再次訪問該URL就不會從緩存響應;

  測試:

  提示:把/index.html的緩存項修剪以後,用戶再次訪問到/index.html資源時,從響應首部就可以知道它沒有被緩存命中;說明緩存項修剪時成功的;

  當然在命令行中可以直接使用ban命令修剪緩存,在配置文件中,我們也可以來使用ban函數來對緩存項進行修剪;如下

   提示:以上紅框中的內容表示用戶的請求方法是BAN  就執行ban(“req.http.host == ” + req.http.host + “&& req.url ==” + req.url),然後通過synth()合成一響應碼為200的頁面響應給用戶;這裡的ban函數參數部分就是一字符串合成;如果用戶請求的host是192.168.0.99 ,url是/index.html;那麼ban函數參數部分就是req.http.host == 192.168.0.99:8000 && req.url == /index.html ,就相當在命令行執行ban req.http.host == 192.168.0.99:8000 && req.url == /index.html ;這裡特別提示“&&”和 “==”號兩邊必須要有空格,否則會把&&識別成req.http.host的值的一部分;

  測試

   提示:我們在配置文件利用判斷用戶請求的方法來修剪緩存項,這種方式同PURGE的方式類似,都需要用acl去控制可以執行修剪操作的客戶端;通常情況下我們如果是臨時修剪緩存項,用ban命令在命令行修剪,很少寫在配置文件中,通過特定的請求方法去修剪特定的資源緩存;而PURGE和ban相反,PURGE常用於在配置文件中用特定的請求方法修剪指定的url資源緩存項;