如何在 NGINX 中緩存內容

Nginx是一個整合的開源、高性能 Web 伺服器,可加速內容和應用程序交付、增強安全性並提高可擴展性。Nginx最常見的用例之一是內容緩存,這是提高網站性能的最有效方法。

您可以使用NGINX來加速本地源伺服器,方法是將其配置為緩存來自上游伺服器的響應,也可以為內容分發網路(CDNs)創建邊緣伺服器。NGINX 為一些最大的 CDN 提供支持。

當配置為緩存時,NGINX 將:

  • 緩存靜態和動態內容。
  • 通過微緩存提高動態內容性能。
  • 提供陳舊的內容,同時在後台重新驗證以獲得更好的性能。
  • 重寫或設置 Cache-Control 消息頭等。

在這篇文章中,你將學習如何在Linux中配置NGINX作為一個內容緩存,以使您的 Web 伺服器儘可能高效地運行。

前提是你的 Linux 伺服器上已安裝NGINX,配置將在下面介紹。

在 Nginx 上緩存靜態內容

靜態內容是跨頁面保持不變(不改變)的網站內容。靜態內容的示例包括圖像、視頻、文檔等文件;CSS 文件和 JavaScript 文件。

如果您的網站使用了大量靜態內容,那麼您可以通過啟用客戶端緩存來優化其性能,瀏覽器在其中存儲靜態內容的副本以便更快地訪問。

下面的示例配置是一個不錯的選擇,只需將ww.example.com替換為您的網站名稱的URL,並適當修改其路徑名。

server {
    # substitute your web server's URL for www.example.com
    server_name www.example.com;
    root /var/www/example.com/htdocs;
    index index.php;

    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
        try_files $uri =404;
        include fastcgi_params;
        # substitute the socket, or address and port, of your WordPress server
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        #fastcgi_pass 127.0.0.1:9000;
 	}   

    location ~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg                  |jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid                  |midi|wav|bmp|rtf)$ {
        expires max;
        log_not_found off;
        access_log off;
    }}

在 Nginx 上緩存動態內容

NGINX使用位於本地文件系統某處的基於磁碟的持久緩存。因此,首先創建用於存儲緩存內容的本地磁碟目錄。

# mkdir -p /var/cache/nginx

接下來,在緩存目錄上設置適當的許可權。它應該由NGINX用戶 ( nginx ) 和組 ( nginx ) 擁有,如下所示:

# chown nginx:nginx /var/cache/nginx

現在繼續在下面的部分中進一步了解如何在 Nginx 上啟用動態內容。

在 NGINX 中啟用 FastCGI 緩存

FastCGI(或FCGI)是一種廣泛使用的協議,用於將PHP等互動式應用程序與NGINX等 Web 伺服器連接起來。它是CGI(通用網關介面)的擴展。

FCGI的主要優點是它在單個進程中管理多個 CGI 請求。沒有它,網路伺服器必須為每個客戶端對服務的請求打開一個新進程(必須對其進行控制、處理一個請求,然後關閉)。

為了在LEMP 堆棧部署中處理PHP腳本,NGINX使用FPM(FastCGI 進程管理器)或PHP-FPM,一種流行的替代 PHP FastCGI 實現。一旦PHP-FPM進程運行,NGINX被配置為將請求代理到它進行處理。因此,NGINX 也可以配置為緩存來自PHP-FPM後端應用程序伺服器的響應。

在NGINX下,FastCGI內容緩存是使用在 NGINX 配置結構fastcgi_cache_path中的頂級http{}上下文中調用的指令聲明的。您還可以添加fastcgi_cache_key定義緩存的鍵(請求標識符)。

此外,要讀取上游緩存狀態,請在上下文中添加add_header X-Cache-Status指令http{} —— 這對於調試目的很有用。

假設您站點的伺服器塊配置文件位於/etc/nginx/conf.d/testapp.conf/etc/nginx/sites-available/testapp.conf(在 Ubuntu 及其衍生版本下),打開編輯文件並添加文件頂部的以下行。

fastcgi_cache_path /var/cache/NGINX levels=1:2 keys_zone=CACHEZONE:10m; inactive=60m max_size=40m;fastcgi_cache_key "$scheme$request_method$host$request_uri";add_header X-Cache $upstream_cache_status;

fastcgi_cache_path指令指定參數的數量,它們是:

  • /var/cache/nginx – 緩存的本地磁碟目錄的路徑。
  • levels - 定義緩存的層次結構級別,它在/var/cache/nginx下設置了兩級目錄層次結構。
  • keys_zone (name:size) – 啟用共享內存區域的創建,其中存儲了所有活動密鑰和有關數據(元)的信息。請注意,將密鑰存儲在內存中加快了檢查過程,使 NGINX 更容易確定它是MISS還是HIT,而無需檢查磁碟上的狀態。
  • 非活動 - 指定在指定時間內未訪問的緩存數據從緩存中刪除的時間量,無論其新鮮度如何。在我們的示例配置中,值60m意味著在 60 之後未訪問的文件將從緩存中刪除。
  • max_size – 指定緩存的最大大小。您可以在此處使用更多參數(閱讀 NGINX 文檔了解更多信息)。

fastcgi_cache_key指令中的變數如下所述。

NGINX 使用它們來計算請求的密鑰(標識符)。重要的是,要向客戶端發送緩存響應,請求必須與緩存響應具有相同的鍵。

  • $scheme – 請求方案,HTTP 或 HTTPS
  • $request_method – 請求方法,通常是「 GET 」或「 POST 」。
  • $host - 這可以是請求行中的主機名,或「 Host 」請求頭欄位中的主機名,或與請求匹配的伺服器名稱,按優先順序排列。
  • $request_uri – 表示完整的原始請求 URI(帶參數)。

此外,add_header X-Cache-Status $upstream_cache_status指令中的變數是針對 NGINX 響應的每個請求計算的,無論是MISS(在緩存中找不到響應,從應用程序伺服器獲取)還是HIT(從緩存提供的響應)或任何其他支持的值。

接下來,在location將 PHP 請求傳遞給PHP-FPM的指令中,使用這些fastcgi_cache指令來激活您剛剛在上面定義的緩存。

fastcgi_cache_valid還可以使用如圖所示的指令為不同的響應設置緩存時間。

fastcgi_cache CACHEZONE;fastcgi_cache_valid  60m;

如果在我們的例子中只指定緩存時間,則只有200、301和302響應被緩存。但您也可以明確指定響應或使用 any(對於任何響應代碼):

fastcgi_cache CACHEZONE;fastcgi_cache_valid 200  301 203 60m;fastcgi_cache_valid 404 10m;OR
fastcgi_cache CACHEZONE;fastcgi_cache_valid  any 10m;

在Nginx上微調FastCGI緩存性能

要設置在緩存響應之前必須發出具有相同鍵的請求的最小次數,請在or或上下文中包含fastcgi_cache_min_uses指令。http{}server{}location{}

fastcgi_cache_min_uses 3

要使用帶有" If-Modified-Since 「和」 If-None-Match "報頭欄位的條件請求來重新驗證過期的緩存項,請在http{}或server{}或location{}上下文中添加fastcgi_cache_revalidate指令。

fastcgi_cache_revalidate on;

你也可以在location指令中使用proxy_cache_use_stale指令,來指示NGINX在源伺服器或FCGI伺服器宕機時傳遞緩存的內容。

此示例配置意味著,當NGINX從上游伺服器接收到錯誤、超時和任何指定的錯誤,並且緩存的內容中有請求文件的過期版本時,它會提交過期文件。

proxy_cache_use_stale error timeout http_500;

另一個微調 FCGI 緩存性能的有用指令是fastcgi_cache_background_updateproxy_cache_use_stale指令結合使用。當設置為 on 時,當客戶端請求過期文件或正在從上游伺服器更新文件時,它指示NGINX提供過期的內容。

fastcgi_cache_background_update on;

fastcgi_cache_lock也很有用,可以對緩存性能進行微調,如果多個客戶端請求相同的內容,而這些內容不在緩存中,NGINX只會將第一個請求轉發給上游伺服器,緩存響應,然後從緩存中處理其他客戶端請求。

fastcgi_cache_lock on;

在NGINX配置文件中進行上述所有更改後,保存並關閉它。然後在重新啟動 NGINX 服務之前檢查配置結構是否有任何語法錯誤。

# nginx -t# systemctl restart nginx

接下來,測試緩存是否正常運行,嘗試使用以下curl 命令訪問您的 Web 應用程序或站點(第一次應指示MISS,但後續請求應指示HIT,如屏幕截圖所示)。

# curl -I http://testapp.tecmint.com


這是另一個顯示 NGINX 提供陳舊數據的屏幕截圖。

添加例外以繞過緩存

使用fastcgi_cache_bypass指令,可以設置NGINX不應該將緩存的響應發送給客戶端。要讓NGINX完全不緩存來自上游伺服器的響應,可以使用fastcgi_no_cache

例如,如果您希望POST請求和帶有查詢字元串的url總是轉到PHP。首先,聲明一個if語句,如下所示設置條件。

set $skip_cache 0; if ($request_method = POST) { 
	set $skip_cache 1; } 

然後使用fastcgi_cache_bypassfastcgi_no_cache指令在location指令中激活上述異常,該指令將PHP請求傳遞給PHP- fpm

fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache;

對於站點的許多其他部分,您可能不希望啟用內容緩存。下面是一個NGINX配置來提高WordPress站點性能的例子,請看nginx.com的博客。

要使用它,需要進行更改(如域、路徑、文件名等),以反映環境中存在的內容。

fastcgi_cache_path /var/run/NGINX-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m; fastcgi_cache_key "$scheme$request_method$host$request_uri"; server { 
	server_name example.com www.example.com; 
	root /var/www/example.com; 
	index index.php; 
	access_log /var/log/NGINX/example.com.access.log; 
	error_log /var/log/NGINX/example.com.error.log; 
	set $skip_cache 0; 
	# POST requests and URLs with a query string should always go to PHP 	
	if ($request_method = POST) { 
		set $skip_cache 1; 
	} 
	if ($query_string != "") {
		set $skip_cache 1; 
	} 
	# Don't cache URIs containing the following segments 
	if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php |sitemap(_index)?.xml") { 
		set $skip_cache 1; 
	} 
	# Don't use the cache for logged-in users or recent commenters 
	if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass |wordpress_no_cache|wordpress_logged_in") {
		set $skip_cache 1; 
	} 
	location / { 
		try_files $uri $uri/ /index.php?$args; 
	} 
	location ~ .php$ { 
		try_files $uri /index.php; 
		include fastcgi_params; 
		fastcgi_pass unix:/var/run/php5-fpm.sock; 
		fastcgi_cache_bypass $skip_cache; 
		fastcgi_no_cache $skip_cache; 
		fastcgi_cache WORDPRESS; 
		fastcgi_cache_valid 60m; 
	} 
	location ~ /purge(/.*) {
		fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1"; 
	} 
	location ~* ^.+.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg |gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi |wav|bmp|rtf)$ { 
		access_log off; 
		log_not_found off; 
		expires max; 
	} 
	location = /robots.txt { 
		access_log off; 
		log_not_found off; 
	}
	location ~ /. { 
		deny all; 
		access_log off; 
		log_not_found off; 
	} }

在 NGINX 中啟用代理緩存

NGINX也支持緩存來自其他代理伺服器的響應(由proxy_pass指令定義)。在這個測試案例中,我們使用NGINX作為Node.js web應用程序的反向代理,所以我們將啟用NGINX作為Node.js應用程序的緩存。這裡使用的所有配置指令與上一節FastCGI指令的含義相似,所以我們不再解釋它們。

要啟用來自代理伺服器的響應緩存,需要在頂級http{}上下文中包含proxy_cache_path指令。要指定如何緩存請求,你也可以添加proxy_cache_key指令,如下所示。

proxy_cache_path /var/cache/nginx app1 keys_zone=PROXYCACHE:100m inactive=60m max_size=500m;proxy_cache_key  "$scheme$request_method$host$request_uri";add_header X-Cache-Status $upstream_cache_status;proxy_cache_min_uses 3;

接下來,在 location 指令中激活緩存。

location / {
	proxy_pass http://127.0.0.1:3000;
	proxy_cache        PROXYCACHE;
	proxy_cache_valid 200 302 10m;
	proxy_cache_valid 404      1m;}

要定義 NGINX 不發送緩存內容並且根本不緩存來自上游伺服器的響應的條件,包括proxy_cache_bypassproxy_no_cache

proxy_cache_bypass  $cookie_nocache $arg_nocache$arg_comment;proxy_no_cache        $http_pragma $http_authorization;

微調代理緩存性能

以下指令可用於微調代理緩存的性能。它們也與 FastCGI 指令具有相同的含義。

proxy_cache_min_uses 3;proxy_cache_revalidate on;proxy_cache_use_stale error timeout updating http_500;proxy_cache_background_update on;proxy_cache_lock on;

有關更多信息和緩存配置指令,請參閱兩個主要模塊ngx_http_fastcgi_module和ngx_http_proxy_module的文檔。