如何在nginx中緩存內(nèi)容
NGINX是一個(gè)整合的開源、高性能 Web 服務(wù)器,可加速內(nèi)容和應(yīng)用程序交付、增強(qiáng)安全性并提高可擴(kuò)展性。Nginx最常見的用例之一是內(nèi)容緩存,這是提高網(wǎng)站性能的最有效方法。

您可以使用NGINX來加速本地源服務(wù)器,方法是將其配置為緩存來自上游服務(wù)器的響應(yīng),也可以為內(nèi)容分發(fā)網(wǎng)絡(luò)(CDNs)創(chuàng)建邊緣服務(wù)器。NGINX 為一些最大的 CDN 提供支持。
當(dāng)配置為緩存時(shí),NGINX 將:
緩存靜態(tài)和動(dòng)態(tài)內(nèi)容。
通過微緩存提高動(dòng)態(tài)內(nèi)容性能。
提供陳舊的內(nèi)容,同時(shí)在后臺(tái)重新驗(yàn)證以獲得更好的性能。
重寫或設(shè)置 Cache-Control 消息頭等。
在這篇文章中,你將學(xué)習(xí)如何在Linux中配置NGINX作為一個(gè)內(nèi)容緩存,以使您的 Web 服務(wù)器盡可能高效地運(yùn)行。
前提是你的 Linux 服務(wù)器上已安裝NGINX,配置將在下面介紹。
在 Nginx 上緩存靜態(tài)內(nèi)容
靜態(tài)內(nèi)容是跨頁(yè)面保持不變(不改變)的網(wǎng)站內(nèi)容。靜態(tài)內(nèi)容的示例包括圖像、視頻、文檔等文件;CSS 文件和 JavaScript 文件。
如果您的網(wǎng)站使用了大量靜態(tài)內(nèi)容,那么您可以通過啟用客戶端緩存來優(yōu)化其性能,瀏覽器在其中存儲(chǔ)靜態(tài)內(nèi)容的副本以便更快地訪問。
下面的示例配置是一個(gè)不錯(cuò)的選擇,只需將ww.example.com替換為您的網(wǎng)站名稱的URL,并適當(dāng)修改其路徑名。
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 上緩存動(dòng)態(tài)內(nèi)容
NGINX使用位于本地文件系統(tǒng)某處的基于磁盤的持久緩存。因此,首先創(chuàng)建用于存儲(chǔ)緩存內(nèi)容的本地磁盤目錄。
# mkdir -p /var/cache/nginx
接下來,在緩存目錄上設(shè)置適當(dāng)?shù)臋?quán)限。它應(yīng)該由NGINX用戶 ( nginx ) 和組 ( nginx ) 擁有,如下所示:
# chown nginx:nginx /var/cache/nginx
現(xiàn)在繼續(xù)在下面的部分中進(jìn)一步了解如何在 Nginx 上啟用動(dòng)態(tài)內(nèi)容。
在 NGINX 中啟用 FastCGI 緩存
FastCGI(或FCGI)是一種廣泛使用的協(xié)議,用于將PHP等交互式應(yīng)用程序與NGINX等 Web 服務(wù)器連接起來。它是CGI(通用網(wǎng)關(guān)接口)的擴(kuò)展。
FCGI的主要優(yōu)點(diǎn)是它在單個(gè)進(jìn)程中管理多個(gè) CGI 請(qǐng)求。沒有它,網(wǎng)絡(luò)服務(wù)器必須為每個(gè)客戶端對(duì)服務(wù)的請(qǐng)求打開一個(gè)新進(jìn)程(必須對(duì)其進(jìn)行控制、處理一個(gè)請(qǐng)求,然后關(guān)閉)。
為了在LEMP 堆棧部署中處理PHP腳本,NGINX使用FPM(FastCGI 進(jìn)程管理器)或PHP-FPM,一種流行的替代 PHP FastCGI 實(shí)現(xiàn)。一旦PHP-FPM進(jìn)程運(yùn)行,NGINX被配置為將請(qǐng)求代理到它進(jìn)行處理。因此,NGINX 也可以配置為緩存來自PHP-FPM后端應(yīng)用程序服務(wù)器的響應(yīng)。
在NGINX下,F(xiàn)astCGI內(nèi)容緩存是使用在 NGINX 配置結(jié)構(gòu)fastcgi_cache_path中的頂級(jí)http{}上下文中調(diào)用的指令聲明的。您還可以添加fastcgi_cache_key定義緩存的鍵(請(qǐng)求標(biāo)識(shí)符)。
此外,要讀取上游緩存狀態(tài),請(qǐng)?jiān)谏舷挛闹刑砑觓dd_header X-Cache-Status指令http{}?—— 這對(duì)于調(diào)試目的很有用。
假設(shè)您站點(diǎn)的服務(wù)器塊配置文件位于/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指令指定參數(shù)的數(shù)量,它們是:
/var/cache/nginx?– 緩存的本地磁盤目錄的路徑。
levels?- 定義緩存的層次結(jié)構(gòu)級(jí)別,它在/var/cache/nginx下設(shè)置了兩級(jí)目錄層次結(jié)構(gòu)。
keys_zone (name:size)?– 啟用共享內(nèi)存區(qū)域的創(chuàng)建,其中存儲(chǔ)了所有活動(dòng)密鑰和有關(guān)數(shù)據(jù)(元)的信息。請(qǐng)注意,將密鑰存儲(chǔ)在內(nèi)存中加快了檢查過程,使 NGINX 更容易確定它是MISS還是HIT,而無需檢查磁盤上的狀態(tài)。
非活動(dòng)?- 指定在指定時(shí)間內(nèi)未訪問的緩存數(shù)據(jù)從緩存中刪除的時(shí)間量,無論其新鮮度如何。在我們的示例配置中,值60m意味著在 60 之后未訪問的文件將從緩存中刪除。
max_size?– 指定緩存的最大大小。您可以在此處使用更多參數(shù)(閱讀 NGINX 文檔了解更多信息)。
fastcgi_cache_key指令中的變量如下所述。
NGINX 使用它們來計(jì)算請(qǐng)求的密鑰(標(biāo)識(shí)符)。重要的是,要向客戶端發(fā)送緩存響應(yīng),請(qǐng)求必須與緩存響應(yīng)具有相同的鍵。
$scheme?– 請(qǐng)求方案,HTTP 或 HTTPS。
$request_method?– 請(qǐng)求方法,通常是“ GET ”或“ POST ”。
$host?- 這可以是請(qǐng)求行中的主機(jī)名,或“ Host ”請(qǐng)求頭字段中的主機(jī)名,或與請(qǐng)求匹配的服務(wù)器名稱,按優(yōu)先順序排列。
$request_uri?– 表示完整的原始請(qǐng)求 URI(帶參數(shù))。
此外,add_header X-Cache-Status $upstream_cache_status指令中的變量是針對(duì) NGINX 響應(yīng)的每個(gè)請(qǐng)求計(jì)算的,無論是MISS(在緩存中找不到響應(yīng),從應(yīng)用程序服務(wù)器獲取)還是HIT(從緩存提供的響應(yīng))或任何其他支持的值。
接下來,在location將 PHP 請(qǐng)求傳遞給PHP-FPM的指令中,使用這些fastcgi_cache指令來激活您剛剛在上面定義的緩存。
fastcgi_cache_valid還可以使用如圖所示的指令為不同的響應(yīng)設(shè)置緩存時(shí)間。
fastcgi_cache CACHEZONE;fastcgi_cache_valid ?60m;

如果在我們的例子中只指定緩存時(shí)間,則只有200、301和302響應(yīng)被緩存。但您也可以明確指定響應(yīng)或使用 any(對(duì)于任何響應(yīng)代碼):
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上微調(diào)FastCGI緩存性能
要設(shè)置在緩存響應(yīng)之前必須發(fā)出具有相同鍵的請(qǐng)求的最小次數(shù),請(qǐng)?jiān)趏r或上下文中包含fastcgi_cache_min_uses指令。http{}server{}location{}
fastcgi_cache_min_uses 3

要使用帶有" If-Modified-Since “和” If-None-Match "報(bào)頭字段的條件請(qǐng)求來重新驗(yàn)證過期的緩存項(xiàng),請(qǐng)?jiān)趆ttp{}或server{}或location{}上下文中添加fastcgi_cache_revalidate指令。
fastcgi_cache_revalidate on;

你也可以在location指令中使用proxy_cache_use_stale指令,來指示NGINX在源服務(wù)器或FCGI服務(wù)器宕機(jī)時(shí)傳遞緩存的內(nèi)容。
此示例配置意味著,當(dāng)NGINX從上游服務(wù)器接收到錯(cuò)誤、超時(shí)和任何指定的錯(cuò)誤,并且緩存的內(nèi)容中有請(qǐng)求文件的過期版本時(shí),它會(huì)提交過期文件。
proxy_cache_use_stale error timeout http_500;

另一個(gè)微調(diào) FCGI 緩存性能的有用指令是fastcgi_cache_background_update與proxy_cache_use_stale指令結(jié)合使用。當(dāng)設(shè)置為 on 時(shí),當(dāng)客戶端請(qǐng)求過期文件或正在從上游服務(wù)器更新文件時(shí),它指示NGINX提供過期的內(nèi)容。
fastcgi_cache_background_update on;

fastcgi_cache_lock也很有用,可以對(duì)緩存性能進(jìn)行微調(diào),如果多個(gè)客戶端請(qǐng)求相同的內(nèi)容,而這些內(nèi)容不在緩存中,NGINX只會(huì)將第一個(gè)請(qǐng)求轉(zhuǎn)發(fā)給上游服務(wù)器,緩存響應(yīng),然后從緩存中處理其他客戶端請(qǐng)求。
fastcgi_cache_lock on;

在NGINX配置文件中進(jìn)行上述所有更改后,保存并關(guān)閉它。然后在重新啟動(dòng) NGINX 服務(wù)之前檢查配置結(jié)構(gòu)是否有任何語法錯(cuò)誤。
nginx -t# systemctl restart nginx

接下來,測(cè)試緩存是否正常運(yùn)行,嘗試使用以下curl 命令訪問您的 Web 應(yīng)用程序或站點(diǎn)(第一次應(yīng)指示MISS,但后續(xù)請(qǐng)求應(yīng)指示HIT,如屏幕截圖所示)。

這是另一個(gè)顯示 NGINX 提供陳舊數(shù)據(jù)的屏幕截圖。

添加例外以繞過緩存
使用fastcgi_cache_bypass指令,可以設(shè)置NGINX不應(yīng)該將緩存的響應(yīng)發(fā)送給客戶端。要讓NGINX完全不緩存來自上游服務(wù)器的響應(yīng),可以使用fastcgi_no_cache。
例如,如果您希望POST請(qǐng)求和帶有查詢字符串的url總是轉(zhuǎn)到PHP。首先,聲明一個(gè)if語句,如下所示設(shè)置條件。
set $skip_cache 0; if ($request_method = POST) {
set $skip_cache 1; }
然后使用fastcgi_cache_bypass和fastcgi_no_cache指令在location指令中激活上述異常,該指令將PHP請(qǐng)求傳遞給PHP- fpm。
fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache;
對(duì)于站點(diǎn)的許多其他部分,您可能不希望啟用內(nèi)容緩存。下面是一個(gè)NGINX配置來提高WordPress站點(diǎn)性能的例子,請(qǐng)看nginx.com的博客。
要使用它,需要進(jìn)行更改(如域、路徑、文件名等),以反映環(huán)境中存在的內(nèi)容。
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也支持緩存來自其他代理服務(wù)器的響應(yīng)(由proxy_pass指令定義)。在這個(gè)測(cè)試案例中,我們使用NGINX作為Node.js web應(yīng)用程序的反向代理,所以我們將啟用NGINX作為Node.js應(yīng)用程序的緩存。這里使用的所有配置指令與上一節(jié)FastCGI指令的含義相似,所以我們不再解釋它們。
要啟用來自代理服務(wù)器的響應(yīng)緩存,需要在頂級(jí)http{}上下文中包含proxy_cache_path指令。要指定如何緩存請(qǐng)求,你也可以添加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 不發(fā)送緩存內(nèi)容并且根本不緩存來自上游服務(wù)器的響應(yīng)的條件,包括proxy_cache_bypass和proxy_no_cache。
proxy_cache_bypass ?$cookie_nocache $arg_nocache$arg_comment;proxy_no_cache ? ? ? ?$http_pragma $http_authorization;
微調(diào)代理緩存性能
以下指令可用于微調(diào)代理緩存的性能。它們也與 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;
有關(guān)更多信息和緩存配置指令,請(qǐng)參閱兩個(gè)主要模塊ngx_http_fastcgi_module和ngx_http_proxy_module的文檔。