問題描述
有兩臺服務器,一臺是外網的網關服務器,一臺是內網的資源服務器,但是兩臺服務器距離很遠(跨省),頁面中依賴大量插件資源,加載耗時久,本章重點講解Nginx代理緩存靜態資源。
解決思路
- CDN
- 開啟gzip壓縮
- 圖片格式優化,找到大圖片
- 外網服務器進行靜態資源緩存
proxy_cache工作原理
Nginx 的 proxy_cache 模塊允許 Nginx 作為反向代理服務器時緩存后端服務器的響應。以下是 proxy_cache 模塊的工作原理:
- 請求到達:客戶端向 Nginx 發送請求。
- 緩存查找:Nginx 首先檢查請求是否命中緩存。這是通過查找共享內存中的緩存鍵(由 proxy_cache_key 定義)來完成的。
- 緩存命中:如果請求命中緩存,Nginx 直接從緩存中讀取響應并返回給客戶端。
- 緩存未命中:如果請求未命中緩存,Nginx 將請求轉發到后端服務器。
- 后端響應:后端服務器處理請求并返回響應給 Nginx。
- 緩存存儲:Nginx 將后端服務器的響應存儲在本地文件系統中,同時在共享內存中更新緩存鍵和元數據。
- 返回響應:Nginx 將后端服務器的響應返回給客戶端,并根據 proxy_cache_valid 指令設置的規則決定緩存時間。
配置
# 設置日志格式,$upstream_cache_status代表是否命中緩存
# $upstream_cache_status的返回值有7個:
# HIT表示緩存命中
# MISS表示未命中,請求被傳送到后端
# EXPIRED表示緩存已經過期,請求被傳送到后端
# UPDATING表示正在更新緩存,將使用舊的應答
# STALE表示無法從后端服務器更新緩存時,返回了舊的緩存內容
# BYPASS表示緩存被繞過了
# REVALIDATED表示啟用proxy_cache_revalidate指令后,當緩存內容過期時,Nginx通過一次If-Modified-Since的請求頭去驗證緩存內容是否過期,此時會返回該狀態
log_format main '$remote_addr - $remote_user [$request_time] [$time_local] "$request" ''$upstream_cache_status ' '$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';
# 打開日志格式化功能,如果這里不打開的話,上面的格式化不生效
access_log logs/access.log main;# 設置緩存區信息
# levels:指定該緩存空間對應的目錄,最多可以設置3層,每層取值為1|2;例如:levels=1:2 緩存空間有兩層目錄,第一次是1個字母,第二次是2個字母
proxy_cache_path /app/nginx/js_cache levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;# --------------以下為server中的配置---------------
location / {proxy_pass http://ip:端口;
}
# 啟用緩存
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ioc|ico|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma|css|js)$ {proxy_pass http://ip:端口;proxy_cache my_cache;# proxy_cache_valid設置不同響應碼的緩存過期時間# HTTP 206 Partial Content(部分內容)狀態碼表示服務器成功處理了客戶端?請求資源部分內容?的GET請求,主要應用于支持范圍請求(Range Request)的場景,比如文件斷點下載proxy_cache_valid 200 304 206 60m; # 緩存200, 304, 206響應3600秒(1小時)proxy_cache_key $uri; # 緩存鍵的生成方式# add_header X-Cache '$upstream_cache_status from $host'; # 在請求的http響應頭中返回,判斷是否命中緩存
}
proxy_cache_path與proxy_cache_valid中超時時間同時設置,生效控制問題
inactive時間到了,數據刪除。proxy_cache_valid時間到了不會被刪除,但是會認為失效,再次請求時會重新下載。有請求,inactive就刷新計時,valid不變。沒請求,inactive和valid都不變。
分析各種情況:
-
inactive設置1m,valid設置1h
首先,請求進來,cache出現,兩個時間開始倒計時。
情況一:不斷請求這個cache,inactive不斷刷新1m倒計時,直到到達1h,valid過期。這時你去請求了一次,nginx重新去讀取服務器數據,刷新valid倒計時。期間數據一直在緩存里。不請求,就再過1m刪掉。
情況二:兩次請求間隔超過了1min,inactive生效,刪除了這個cache數據,沒了。你再請求,相當于重新去服務器拿了一次數據,inactive和valid倒計時都會重新刷新,不請求,cache里就沒有這份數據了 -
inactive設置1m,valid設置1m
首先,請求進來,cache出現,兩個時間開始倒計時。
情況一:1m內不請求,最后inactive生效刪掉。不請求就沒緩存了,請求了一次,重新從服務器讀取一份,兩個計時刷新。
情況二:1m內請求了一次,inactive時間刷新,但是valid還在計時,所以1m到了后,緩存過期了。你再請求就重新從服務器讀取一份,刷新計時。不請求,就等待1m,由inactive生效刪除了緩存 -
inactive設置1h,valid設置了1m
首先,請求進來,cache出現,兩個時間開始倒計時。
過了1m,緩存過期,數據在沒刪掉。不請求,直到1h到,inactive刪掉緩存。請求了一次,重新從服務器讀取,刷新兩個計時。
所以,通常inactive應該需要設置的比valid中時間長,inactive和valid是配合使用,不是誰時間短覆蓋誰的關系。
緩存清理
清除緩存,直接刪除緩存文件夾,下次請求的時候會重新生成
外網緩存失敗,內網不允許緩存
在生產環境出現過一個問題,在外網服務器nginx配置了緩存信息,日志配置生效,緩存目錄也生成,但是始終沒有生成緩存文件,最后排查發現,在內網的nginx配置了如下禁止緩存的信息,應該將此段內容從內網服務器移到外網上或者使用proxy_ignore_headers
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
add_header Pragma no-cache;
add_header Expires 0;
private:專用于個人的緩存,中間代理、CDN 等不能緩存此響應
public:響應可以被中間代理、CDN 等緩存
參考
nginx proxy_cache緩存詳解(強烈推薦)
nginx配置proxy_cache_path之inactive和proxy_cache_valid對比
Nginx 緩存系統 proxy_cache詳解