nginx快取與優化

kekefund發表於2017-10-14

在瀏覽器和應用伺服器之間,存在多種“潛在”快取,如:

  • 客戶端瀏覽器快取
  • 中間快取
  • 內容分發網路(CDN)
  • 伺服器上的負載均衡和反向代理

    快取,僅在反向代理和負載均衡的層面,就對效能提高有很大的幫助。

為什麼要用快取?

  • 網站的訪問速度更快
  • 減輕源伺服器的負擔
  • 提高負載平衡器、反向代理和應用伺服器前端web服務的效能

nginx代理模組快取指令

指令 說明
proxy_cache 定義快取的共享記憶體區域
proxy_cache_bypass 一個或者多個字串變數,變數的值為非空或者非零將會導致響應從上游伺服器獲取而不是快取
proxy_cache_key 用來區分快取檔案的key,作為快取key的一個字串,用於儲存或者獲取快取值。預設值為$scheme$proxy_host$uri$is_args$args
proxy_cache_lock 啟用這個指令,當多個客戶端請求一個快取中不存在的檔案(或稱之為一個MISS),只有這些請求中的第一個被允許傳送至伺服器。其他請求在第一個請求得到滿意結果之後在快取中得到檔案。
proxy_cache_lock_timeout 等待一個請求將出現在快取或者proxy_cache_lock鎖釋放的時間長度
proxy_cache_min_uses 在一個響應被快取為一個key之前需要請求的最小次數
proxy_cache_path 一個放置快取響應和共享zone(keys_zone=name:size)的目錄,用於存放key和響應的後設資料。
proxy_cache_path:keys_zone 設定一個共享記憶體區,用於儲存快取鍵和後設資料,有些類似計時器的用途。
proxy_cache_path:levels 冒號用於分隔在每個級別(1或2)的子目錄名長度,最多三級深;
proxy_cache_path:inactive 在一個不活動的響應被驅除出快取之前待在快取中的最大時間長度;例如設定如60m,則檔案如果在60分鐘之內沒有被請求,則快取管理會自動將其在記憶體中刪除,不管檔案是否過期。
proxy_cache_path:max_size 快取的最大值,當大小超過這個值,快取管理器溢位最近最少使用的快取條目;
proxy_cache_path:loader_files 快取檔案的最大數量,它們的後設資料被每個快取載入程式迭代載入;
proxy_cache_path:loader_sleep 在每個迭代快取載入程式之間停頓的毫秒數;
proxy_cache_path:loader_threshold 快取載入程式迭代花去時間的最大值
proxy_cache_use_stale 在訪問上游伺服器的時候發生錯誤,在這種情況下接受提供過期的快取資料。引數updating告知NGINX在客戶端請求的專案的更新正在原伺服器中下載時傳送舊內容,而不是向伺服器轉發重複的請求
proxy_cache_valid 快取的有效期;指定對200、301或者302有效程式碼快取的時間長度。特定引數any表示對任何響應都快取一定時間長度。
proxy_cache_methods 快取支援的方法,預設為GET,可以改為POST,OPTIONS等

快取策略

  • 首頁快取1分鐘,因為它所包含的連結及檔案列表經常更新
  • 每篇文章都被快取1天,因為一旦寫完它們將不會改變,但我們又不希望快取被填滿,因此需要移除一些舊的快取內容以便滿足空間的需要。
  • 儘量地快取所有影像,因為從磁碟檢索影像檔案是一件比較“昂貴”的操作。
http {
    proxy_cache_path    /var/spool/nginx/articles    keys_zone=ARTICLES:16m    levels=1:2    inactive=1d;
    proxy_cache_path    /var/spool/nginx/images    keys_zone=IMAGES:128m    levels=1:2    inactive=30d;
    proxy_temp_path    /var/spool/nginx;

    server {

        location / {
            # 首頁
            proxy_cache_valid 1m;
        }
        
        location /articles {
            proxy_cache_valid 1d;
        }
    
        location /img {
            proxy_cache_valid 10y;
        }
    }
}

示例

下面的配置設計快取所有的響應6個小時,快取大小為1GB。任何條目儲存重新整理,就是說,在6個小時內被呼叫為超時,有效期為1天。在此時間後,上游伺服器將再次呼叫提供響應。如果上游伺服器由於錯誤、超時、無效頭或者是由於快取條目被升級,那麼過期的條目就會被使用。共享記憶體區、CACHE被定義為10MB,並且在location中使用,在這裡設定快取key,並且也可以從這裡查詢。

http {
    proxy_temp_path  /var/spool/nginx;

    proxy_cache_path  /var/spool/nginx  keys_zone=CACHE:10m  levels=1:2  inactive=6h max_size=1g;
 
    server {
 
        location / {
            # using include to bring in a file with commonly-used settings
            include proxy.conf;
 
            proxy_cache CACHE;
 
            proxy_cache_valid any 1d;
 
            proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
 
            proxy_pass http://upstream;
        }
    }
}

實踐

1,檢測快取狀態

通過新增如下程式碼實現

server {
    listen 80;
    server_name xx.fofpower.com;
    location / {
        proxy_cache api_cache;
        proxy_cache_valid  200 206 304 301 302 1d;        
        proxy_ignore_headers Cache-Control;
        add_header X-Cache-Status $upstream_cache_status;  #新增此行
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://myapi;
    }
}

瀏覽器上看到的狀態可能有:

$upstream_cache_status可能值:
1,MISS——響應在快取中找不到,所以需要在伺服器中取得。
2,HIT——響應包含來自快取的最新有效的內容
3,EXPIRED——快取中的某一項過期了,來自原始伺服器的響應包含最新的內容
4,STALE——內容陳舊是因為原始伺服器不能正確響應。需要配置proxy_cache_use_stale
5,UPDATING——內容過期了,因為相對於之前的請求,響應的入口(entry)已經更新,並且proxy_cache_use_stale的updating已被設定
6,REVALIDATED——proxy_cache_revalidate命令被啟用,NGINX檢測得知當前的快取內容依然有效(If-Modified-Since或者If-None-Match)

2,快取POST請求

NGINX預設支援GET請求的快取,要增加POST,需要設定proxy_cache_methods。
對於POST請求,url相同,body內容不同,如果使用預設的proxy_cache_key,會造成不同的post請求,用了一個快取鍵,返回給前端的資料會錯亂。
解決方案是將post的請求引數也作為key的一部分。

server {
    listen 80;
    server_name www.fofeasy.com;
    add_header X-Cache-Status $upstream_cache_status;
    location / {
        proxy_cache web_cache;
        proxy_cache_valid  200 206 304 301 302 10d;
        proxy_cache_key $uri$request_body; #增加此行
        proxy_cache_methods GET POST;  #增加此行
        proxy_ignore_headers Cache-Control;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://myweb;
    }
}

參考


相關文章