009.Nginx快取及配置

木二發表於2020-07-16

一 瀏覽器快取

1.1 快取概述

快取對於Web至關重要,尤其對於大型高負載Web站點。Nginx快取可作為效能優化的一個重要手段,可以極大減輕後端伺服器的負載。通常對於靜態資源,即較少經常更新的資源,如圖片,css或js等進行快取,從而在每次重新整理瀏覽器的時候,不用重新請求,而是從快取裡面讀取,這樣就可以減輕伺服器的壓力。
Nginx設定快取有兩種方式:
  • proxy_cache_path和proxy_cache
  • Cache-Control和Pragma
  • 對於站點中不經常修改的靜態內容(如圖片,JS,CSS),可以在伺服器中設定expires過期時間,控制瀏覽器快取,達到有效減小頻寬流量,降低伺服器壓力的目的。

    1.2 快取機制

  • 瀏覽器無快取
  • 瀏覽器請求 ---> 無快取 ---> 請求WEB伺服器 ---> 請求響應 ---> 呈現
  • 瀏覽器有快取
  • 瀏覽器請求 ---> 有快取 ---> 校驗過期 ---> 是否有更新 ---> 呈現
  • 校驗是否過期
  • Expires HTTP1.0, Cache-Control(max-age) HTTP1.1
    協議中Etag頭資訊校驗 Etag ()
    Last-Modified頭資訊校驗 Last-Modified (具體時間)

    1.3 Nginx快取型別

  • 伺服器快取
  • clipboard
  • 代理快取
  • clipboard
  • 客戶端快取
  • clipboard

    1.4 Nginx代理快取原理

    clipboard
    第一步:客戶端第一次向Nginx請求資料A;
    第二步:當Nginx發現快取中沒有資料A時,會向服務端請求資料A;
    第三步:服務端接收到Nginx發來的請求,則返回資料A到Nginx,並且快取在Nginx;
    第四步:Nginx返回資料A給客戶端應用;
    第五步:客戶端第二次向Nginx請求資料A;
    第六步:當Nginx發現快取中存在資料A時,則不會請求服務端;
    第七步:Nginx把快取中的資料A返回給客戶端應用。

    1.5 快取內容

    網頁快取是由HTTP訊息頭中的"Cache-control"來控制的,常見的取值有private、no-cache、max-age、must-revalidate等,預設為private。
    其作用根據不同的重新瀏覽方式分為以下幾種情況。
    Cache-directive
    說明
    public
    所有內容都將被快取(客戶端和代理伺服器都可快取)。
    private
    內容只快取到私有快取中(僅客戶端可以快取,代理伺服器不可快取)。
    no-cache
    必須先與伺服器確認返回的響應是否被更改,然後才能使用該響應來滿足後續對同一個網址的請求。因此,如果存在合適的驗證停牌(ETag),no-cache會發起往返通訊來驗證快取的響應,如果資源未被更改,可以避免下載。
    no-store
    所有內容都不會被快取到快取或Internet臨時檔案中,強制快取和對比快取都不會觸發。
    must-revalidation.proxy-revalidation
    如果快取內容失敗,請求必須傳送到伺服器、代理以進行重新驗證。
    max-age=xxx(xxx is numeric)
    快取的內容將在xxx秒失效,這個選項只在HTTP 1.1可用,並如果和Last-Modified一起使用時,優先順序較高。

    1.6 快取規則

    預設情況下,NGINX尊重Cache-Control源伺服器的標頭。它不快取響應Cache-Control設定為Private,No-Cache或No-Store或Set-Cookie在響應頭。NGINX只快取GET和HEAD客戶端請求。
    如下配置可覆蓋這些預設值:
  • proxy_buffering預設為on,若proxy_buffering設定為off,則NGINX不會快取響應。
  • proxy_ignore_headers可以配置忽略Cache-Control:
  •   1 location /images/ {
      2     proxy_cache my_cache;
      3     proxy_ignore_headers Cache-Control;
      4     proxy_cache_valid any 30m;
      5     # ...
      6 }

    二 Nginx快取配置項

    2.1 expires配置

    語法:expires [modified] time;
    expires epoch | max | off;
    預設值:expires off; #靜態快取
    作用:Expires是服務端返回的到期時間。如果下一次請求如果小於服務端返回的過期時間,則直接使用快取資料。Expires針對HTTP1.0的東西,當前通常瀏覽器預設都是使用HTTP1.1。而且由於該值是有服務端生成,而客戶端的時間和服務端的時間有可能不一致,導致存在一定誤差。所以HTTP1.1使用Cache-Control替代。
    可配置段:http, server, location, if in location
    引數釋義:
    max啟用後為:Expires: Thu, 31 Dec 2037 23:55:55 GMT Cache-Control: max-age=315360000 (10年);
    epoch啟用後為:Expires: Thu, 01 Jan 1970 00:00:01 GMT Cache-Control: no-cache;
    time:設定具體時間,可以攜帶單位(通過@),如:表示一天內的下午3點30分後失效expires @15h@30m;time是負數:表示”Cache-Control: no-cache”;time是正數或零:”Cache-Control: max-age=t”,其中t單位為秒。
    配置示例:
      1 server {
      2     listen       80;
      3     server_name  xxx.xxx.com;
      4     root         /app/xxx/html/;
      5     location ~ .*\.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$
      6     {
      7         expires      7d;
      8     }
      9 
     10     location ~ .*\.(?:js|css)$
     11     {
     12         expires      7d;
     13     }
     14 
     15     location ~ .*\.(?:htm|html)$    #不快取html
     16     {
     17         add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
     18     }
     19 }
    對於http協議頭Cache-Control,其值釋義如下:
  • Public:指示響應可被任何快取區快取。
  • Private:指示對於單個使用者的整個或部分響應訊息,不能被共享快取處理。這允許伺服器僅僅描述當使用者的部分響應訊息,此響應訊息對於其他使用者的請求無效。
  • no-cache:指示請求或響應訊息不能快取。
  • no-store:用於防止重要的資訊被無意的釋出。在請求訊息中傳送將使得請求和響應訊息都不使用快取。
  • max-age:指示客戶機可以接收生存期不大於指定時間(以秒為單位)的響應。
  • min-fresh:指示客戶機可以接收響應時間小於當前時間加上指定時間的響應。
  • max-stale:指示客戶機可以接收超出超時期間的響應訊息。如果指定max-stale訊息的值,那麼客戶機可以接收超出超時期指定值之內的響應訊息。
  • 2.2 proxy_cache配置

    語法:proxy_cache zone | off;
    預設:proxy_cache off;
    可配置段:http, server, location
    作用:設定是否開啟對後端響應的快取,如果開啟的話,引數值就是zone的名稱。
    示例:
      1 proxy_cache mycache;

    2.3 proxy_cache_path配置

    語法:proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size[inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
    預設值:——
    可配置段:http
    作用:指定快取位置、快取名稱、記憶體中快取內容後設資料資訊大小限制、快取總大小限制。快取位置是一個目錄應該先建立好,nginx並不會幫我們建立這個快取目錄。
    引數釋義:
  • path:定義快取檔案存放位置;
  • levels:定義快取路徑的目錄層級,預設所有快取檔案都放在上面指定的根路徑中,最多三級,每層目錄長度為1或2位元組;
  • keys_zone:name表示共享記憶體名稱,用於在共享記憶體中定義一塊儲存區域來存放快取的 key 和 metadata(類似於使用次數),這樣 nginx 可以快速判斷一個 request 是否命中快取。由proxy_cache指令使用;size表示共享記憶體大小,1mb大約可以存放8000個key;
  • max_size:設定快取大小的上限。它是可選的,不指定值允許快取增長以使用所有可用磁碟空間。當快取大小達到限制時,稱為快取管理器的程式將刪除最近最少用於將快取大小恢復到限制之下的檔案;
  • inactive:在inactive時間內沒有被訪問的快取會被淘汰掉,預設是10分鐘;
  • use_temp_path:如果為 off,則 nginx 會將快取檔案直接寫入指定的 cache 檔案中,而不使用 temp_path 指定的臨時儲存路徑。
  • 注意:inactive 和 expired 配置項的含義是不同的,expired 只是判斷過期時間,不會刪除快取;而 inactive 是直接刪除過期快取。
    配置示例:
      1 http {
      2     ...
      3     // 快取目錄:/data/nginx/cache
      4     // 快取名稱:one
      5     // 快取佔用記憶體空間:10m
      6     // 快取目錄級別為2
      7     // 快取最大時間為60分鐘
      8     // 載入器每次迭代過程最多執行300毫秒
      9     // 載入器每次迭代過程中最多載入200個檔案
     10     // 快取硬碟空間最多為 200m
     11     proxy_cache_path /data/nginx/cache  levels=1:2 keys_zone=one:10m inactive=60m loader_threshold=300 loader_files=200 max_size=200m;
     12     server {
     13         listen 8080;
     14         // 使用名稱為one的快取
     15         proxy_cache one;
     16         location / {
     17             // 此location中使用預設的快取配置
     18             proxy_pass http://backend1;
     19         }
     20         location /some/path {
     21             proxy_pass http://backend2;
     22         // 快取有效期為1分鐘
     23             proxy_cache_valid any 1m;
     24             // 被請求3次以上時才快取
     25             proxy_cache_min_uses 3;
     26         // 請求中有下面引數值時不走快取
     27             proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
     28         }
     29     }
     30 }
    提示:在如上快取工作中有兩個附加程式:
  • 快取管理器:定期檢查快取狀態,看快取總量是否超出限制,如果超出,就移除其中最少使用的部分
  • 快取載入器:載入器只在nginx啟動後執行一次,把快取內容的後設資料資訊載入到記憶體空間,如果一次性載入全部快取資訊,會大量消耗資源,使nginx在啟動後的幾分鐘裡變慢,為避免此問題,有3種載入策略:
  • loader_threshold:指定每次載入執行的時間
  • loader_files:每次最多載入的數量
  • loader_sleeps:每次載入的延時
  • 2.3 proxy_cache_valid配置

    語法:proxy_cache_valid [code ...] time;
    預設值:——
    可配置段:http, server, location
    作用:預設情況下,快取的內容是長期存留的,除非快取的總量超出限制,此欄位可配置不同的響應碼快取不同的時長,即指定快取的有效期。
    示例:
    響應狀態碼為200 302時,10分鐘有效;
    響應狀態碼為404時,1分鐘有效;
      1 ……
      2 proxy_cache_valid 200 302 10m;
      3 proxy_cache_valid 404      1m;
      4 ……
    對應任何狀態碼,5分鐘有效;
      1 ……
      2 proxy_cache_valid any 5m;
      3 ……

    2.4 proxy_cache_methods配置

    語法:proxy_cache_methods GET | HEAD | POST ...;
    預設值:proxy_cache_methods GET HEAD;
    可配置段:http, server, location
    作用:對哪些方法的請求進行快取。
    提示:更多快取配置參考:https://shuwoom.com/?p=4311、https://linux.cn/article-5945-1.html。
    第三方快取模組參考:https://www.jianshu.com/p/1ba7d91afa39。

    2.5 proxy_cache_key string

    語法:proxy_cache_key string;
    預設值:proxy_cache_key $scheme$proxy_host$request
    可配置段:http, server, location
    作用:用於設定不同維度進行快取,即給快取設定key。如快取url。
    示例:

    2.6 proxy_cache_min_uses

    語法:proxy_cache_min_uses string;
    預設值:proxy_cache_min_uses 1;
    可配置段:http, server, location
    作用:指定請求至少被髮送了多少次以上時才快取,可以防止低頻請求被快取。
    示例:
      1 ……
      2 proxy_cache_min_uses 5;
      3 ……
      4 

    2.7 proxy_cache_bypass

    語法:proxy_cache_bypass string;
    預設值:——
    可配置段:http, server, location
    作用:指定哪些響應在某些值不為空或不為0的情況下不走快取。
    示例:
      1 ……
      2 proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
      3 ……
      4 

    2.8 proxy_no_chache string

    語法:proxy_no_chache string;
    預設值:——
    可配置段:http, server, location
    作用:指定定哪些請求不被快取,即響應來自原始伺服器而不是快取。
    示例:
      1 ……
      2 proxy_no_chache $cookie_nocache $arg_nocache $arg_nocache;
      3 ……
      4 

    2.9 proxy_cache_use_stale

    語法:proxy_cache_use_stale off | on;
    預設值:proxy_cache_use_stale off;
    可配置段:http, server, location
    作用:指定在後端伺服器在返回什麼狀態碼的情況下可以使用過期的快取。
    示例:
      1 ……
      2 proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
      3 ……
      4 

    2.10 proxy_cache_lock

    語法:proxy_cache_lock off | on;
    預設值:proxy_cache_lock off;
    可配置段:http, server, location
    作用:預設不開啟,開啟的話則每次只能有一個請求更新相同的快取,其他請求要麼等待快取有資料要麼限時等待鎖釋放。通常在多個客戶端請求快取未命中時,只有第一個請求可以發向原伺服器,其他請求要等待第一個響應返回或者超時後,使用快取響應客戶端。該引數可以合併回源請求,減輕峰值流量下的壓力。
    示例:
      1 ……
      2 proxy_cache_lock on;
      3 ……
      4 

    2.11 proxy_cache_lock_timeout

    語法:proxy_cache_lock_timeout time;
    預設值:proxy_cache_lock_timeout 5s;
    可配置段:http, server, location
    作用:等待快取鎖超時之後將直接請求後端,結果不會被快取。
    示例:
      1 ……
      2 proxy_cache_lock_timeout 5s;
      3 ……
      4 

    三 快取配置例項

    提示:本實驗結合反向代理演示最佳,具體配置參考《010.Nginx正反代理》步驟六。
    參考文件:https://www.myfreax.com/nginx-caching-guide/

    四 快取清除

    4.1 清除快取配置

      1 location ~ /purge(/.*) {
      2         allow       127.0.0.1;
      3         allow       192.168.55.0/24;
      4         deny        all;
      5         proxy_cache_purge cache_one $1$is_args$args;
      6     }
    注意:使用proxy_cache_purge清除快取,必須提前安裝ngx_cache_purge模組,安裝模組必須基於編譯安裝的Nginx。之後使用url訪問即可清除對應快取,如cache.linuxds.com/purge/nginx.png即可清除cache.linuxds.com/nginx.png此檔案的快取。

    4.2 指令碼清除

    清除快取指令碼如下,必須在快取伺服器上執行,
    [root@nginx01 ~]# vi nginx_cache_clean.sh
      1 #!/bin/sh
      2 #****************************************************************#
      3 # ScriptName: nginx_cache_clean.sh
      4 # Author: null
      5 # Create Date: 2020-06-24 00:03
      6 # Modify Author: xhy
      7 # Modify Date: 2020-06-24 00:03
      8 # Version:
      9 #***************************************************************#
     10 echo -e "\n"
     11 echo -n -e "\e[35;1m請輸入Nginx Proxy_cache快取的具體路徑(提示:可使用Tab補全!)\e[0m\e[34;5m:\e[0m"
     12 read -e path
     13 CACHE_DIR=$path
     14 echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
     15 echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
     16 echo -n -e "\e[32;1m請輸入刪除操作的型別:\n1.按檔案型別刪除\t2.按具體檔名刪除\t3.按檔案目錄刪除\n:"
     17 read action
     18      case $action in
     19 1)
     20 echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
     21 echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
     22 echo -n -e "\e[34;1m 請輸入你要刪除的快取檔案型別(多個引數可空格隔開)\e[0m\e[34;5m:\e[0m"
     23 read -a FILE
     24 for i in `echo ${FILE[*]}|sed 's/ /\n/g'`
     25 do
     26 grep -r -a  \.$i ${CACHE_DIR}| awk 'BEGIN {FS=":"} {print $1}'  > /tmp/cache_list.txt
     27  for j in `cat /tmp/cache_list.txt`
     28 do
     29    rm  -rf  $j
     30    echo "$i     $j 刪除成功!"
     31  done
     32 done
     33 ;;
     34 2)
     35 echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
     36 echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
     37 echo -n -e "\e[33;1m 請輸入你要刪除的快取檔案具體名稱(多個引數可空格隔開)\e[0m\e[34;5m:\e[0m"
     38 read -a FILE
     39 for i in `echo ${FILE[*]}|sed 's/ /\n/g'`
     40 do
     41 grep -r -a  $i ${CACHE_DIR}| awk 'BEGIN {FS=":"} {print $1}'  > /tmp/cache_list.txt
     42  for j in `cat /tmp/cache_list.txt`
     43 do
     44    rm  -rf  $j
     45    echo "$i  $j 刪除成功!"
     46  done
     47 done
     48 ;;
     49 3)
     50 echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
     51 echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
     52 echo -n -e "\e[33;1m支援的模式有:\n1.清除網站cache目錄下的所有快取:cache.aa.com/data/cache/\n2.清除網站shop下的所有快取:cache.aa.com/data/upload/shop\n3.清除網站根目錄下的所有快取:cache.aa.com\e[0m\n"
     53 echo -n -e "\e[34;1m 請輸入你要刪除的快取檔案具體目錄\e[0m\e[34;5m:\e[0m"
     54 read -a FILE
     55 for i in `echo ${FILE[*]}|sed 's/ /\n/g'`
     56 do
     57 grep -r -a  "$i" ${CACHE_DIR}| awk 'BEGIN {FS=":"} {print $1}'  > /tmp/cache_list.txt
     58  for j in `cat /tmp/cache_list.txt`
     59 do
     60    rm  -rf  $j
     61    echo "$i  $j 刪除成功!"
     62  done
     63 done
     64 ;;
     65 *)
     66 echo "輸入錯誤,請重新輸入"
     67 ;;
     68 esac
    參考文件:https://lichi6174.github.io/nginx-cache/。

    相關文章