一 瀏覽器緩存
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緩存類型
- 服務器緩存
- 代理緩存
- 客戶端緩存
1.4 Nginx代理緩存原理
第一步:客戶端第一次向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。
其作用根據不同的重新瀏覽方式分為以下幾種情況。
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/。