一、簡介
Nginx版本從0.7.48開始,支持了類似Squid的緩存功能。這個緩存是把URL及相關組合當做Key,用Md5算法對Key進行哈希,得到硬盤上對應的哈希目錄路徑,從而將緩存內容保存在該目錄內。
Nginx Web 緩存服務只能為指定URL或狀態碼設置過期時間,不支持類似Squid的PURGE指令手動清除緩存;但是我們可以通過Nginx的模塊ngx_cache_purge清除指定URL的緩存。
- proxy_cache:緩存后端服務器的內容,可能是任何內容,包括靜態的和動態,減少了nginx與后端通信的次數,節省了傳輸時間和后端寬帶
- fastcgi_cache:緩存fastcgi生成的內容,很多情況是php生成的動態的內容,少了nginx與php的通信的次數,更減輕了php和數據庫(mysql)的壓力,這比用memcached之類的緩存要輕松得多
圖片來自網絡
二、配置
nginx.conf
1
2
3
4
5
|
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"
;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_temp_path /tmp/nginx/fcgi/temp;
|
vhost配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
server {
server_name example.com www.example.com;
access_log /
var
/log/nginx/example.com.access.log;
error_log /
var
/log/nginx/example.com.error.log;
root /
var
/www/example.com/htdocs;
index index.php;
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 =404;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/dev/shm/php-socket;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
include fcgi_cache_params;
}
location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS
"$scheme$request_method$host$1"
;
}
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|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; }
}
|
fcgi_cache_params配置
1
2
3
4
5
6
7
8
9
10
11
12
|
#include fcgi_cache_params;
#fastcgi_cache_valid 200 302 1s;
### fcgi-cache
fastcgi_cache fcgi;
fastcgi_cache_valid 200 302 1s;
fastcgi_cache_valid 404 500 502 503 504 0s;
fastcgi_cache_valid any 1m;
fastcgi_cache_min_uses 1;
fastcgi_cache_use_stale error timeout invalid_header http_500 http_503 updating;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
#add_header X-Cache "$upstream_cache_status - $upstream_response_time";
fastcgi_cache_key
"$scheme$request_method$host$request_uri"
|
大概解釋下各個參數的含義:
fastcgi_cache 該指令用於設置哪個緩存區將被使用,zone_name的值為fastcgi_cache_path指令創建的緩存名稱
fastcgi_cache_path 作用域:http
1
2
3
4
|
fastcgi_cache_path path
[levels=levels] [use_temp_path=
on
|off] keys_zone=name:size [inactive=time]
[max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time]
[purger=
on
|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
|
該指令用於設置緩存文件的存放路徑,示例如下:fastcgi_cache_path /data/nginx/cache levels=1:2 keys_zone=cache_one:100M inactive=1d max_size=10g;
a、levels:指定了該緩存空間有兩層hash目錄,設置緩存目錄層數,levels=1:2,表示創建兩層目錄緩存,最多創建三層。第一層目錄名取fastcgi_cache_key md5的最后一個字符,第二層目錄名取倒數2-3字符,如:fastcgi_cache_key md5為b7f54b2df7773722d382f4809d65029c,則:
1
2
|
levels=1:2為/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
levels=1:2:3為/data/nginx/cache/c/29/650/b7f54b2df7773722d382f4809d65029c
|
b、keys_zone為這個緩存區起名為zone_name,500m指代緩存空間為500MB;
c、inactive=1d 代表如果緩存文件一天內沒有被訪問,則刪除;
d、max_size=30g代表硬盤緩存最大為30G;
設置緩存多個磁盤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
fastcgi_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m max_size=10g inactive=60m use_temp_path=off;
fastcgi_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m max_size=10g inactive=60m use_temp_path=off;
split_clients $request_uri $my_cache {
50%
"my_cache_hdd1"
;
50%
"my_cache_hdd2"
;
}
server {
...
location / {
fastcgi_cache $my_cache;
}
}
|
將緩存文件放入內存中
編輯/etc/fstab 或者 放入 /dev/shm
1
2
3
|
tmpfs /etc/nginx/cache tmpfs defaults,size=100M 0 0
mount -a
df -ah | grep tmpfs
|
需要注意的是fastcgi_cache緩存是先寫在fastcgi_temp_path再移到fastcgi_cache_path,所以這兩個目錄最好在同一個分區,從0.8.9之后可以在不同的分區,不過還是建議放同一分區
fastcgi_cache_methods 該指令用於設置緩存哪些HTTP方法,默認緩存HTTP GET/HEAD方法。
fastcgi_cache_min_uses URL經過多少次請求將被緩存
fastcgi_cache_valid reply_code [reply_code ... ] time
該指令用於對不同返回狀態碼的URL設置不同的緩存時間,例如:
1
2
|
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 404 1m;
|
設置202 302狀態URL緩存10分鍾,404狀態的URL緩存1分鍾。
注意:如果不指定狀態碼,直接指定緩存時間,則只有200,301,302狀態碼會進行緩存。
1
|
fastcgi_cache_valid 5m;
|
any
可以指定緩存任何響應碼
1
2
3
|
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 1m;
|
緩存的參數也可以在響應頭直接設置。這些的優先級高於緩存時間設定使用該指令
- The “X-Accel-Expires” header field sets caching time of a response in seconds. The zero value disables caching for a response. If the value starts with the
@
prefix, it sets an absolute time in seconds since Epoch, up to which the response may be cached. - If the header does not include the “X-Accel-Expires” field, parameters of caching may be set in the header fields “Expires” or “Cache-Control”.
- If the header includes the “Set-Cookie” field, such a response will not be cached.
- If the header includes the “Vary” field with the special value “
*
”, such a response will not be cached (1.7.7). If the header includes the “Vary” field with another value, such a response will be cached taking into account the corresponding request header fields (1.7.7).
fastcgi_cache_key
該指令用來設置Web緩存的Key值,Nginx根據Key值MD5緩存。一般根據host(域名),host(域名),request_uri(請求的路徑)等變量組合成fastcgi_cache_key。
例如:fastcgi_cache_key "schemeschemerequest_methodhosthostrequest_uri";
定義fastcgi_cache的key,示例中就以請求的URI作為緩存的key,Nginx會取這個key的md5作為緩存文件,如果設置了緩存哈希目錄,Nginx會從后往前取相應的位數做為目錄。
注意一定要加上$request_method作為cache key,否則如果HEAD類型的先請求會導致后面的GET請求返回為空
fastcgi_temp_path path [level1 [level2 [level3]]]; 默認為 fastcgi_temp;
該指令用來設置fastcgi_cache臨時文件目錄
1
|
fastcgi_temp_path /spool/nginx/fastcgi_temp 1 2;
|
a temporary file might look like this:
1
|
/spool/nginx/fastcgi_temp/7/45/00000123457
|
fastcgi_cache_use_stale : fastcgi_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_503 | http_403 | http_404 | off ...;
定義哪些情況下用過期緩存
x-cache頭,用於調試
$upstream_response_time為過期時間
$upstream_cache_status 變量表示此請求響應來自cache的狀態,幾種狀態分別為:
- MISS – The response was not found in the cache and so was fetched from an origin server. The response might then have been cached.
- BYPASS – The response was fetched from the origin server instead of served from the cache because the request matched a proxy_cache_bypass directive (see Can I Punch a Hole Through My Cache? below.) The response might then have been cached.
- EXPIRED – The entry in the cache has expired. The response contains fresh content from the origin server.
- STALE – The content is stale because the origin server is not responding correctly, and proxy_cache_use_stale was configured.
- UPDATING – The content is stale because the entry is currently being updated in response to a previous request, and proxy_cache_use_stale updating is configured.
- REVALIDATED – The proxy_cache_revalidate directive was enabled and NGINX verified that the current cached content was still valid (If-Modified-Since or If-None-Match).
- HIT – The response contains valid, fresh content direct from the cache.
有一些情況會影響到cache的命中 這里需要特別注意
- Nginx fastcgi_cache在緩存后端fastcgi響應時,當響應里包含“set-cookie”時,不緩存;
- 當響應頭包含Expires時,如果過期時間大於當前服務器時間,則nginx_cache會緩存該響應,否則,則不緩存;
- 當響應頭包含Cache-Control時,如果Cache-Control參數值為no-cache、no-store、private中任意一個時,則不緩存,如果Cache-Control參數值為max-age時,會被緩存,且nginx設置的cache的過期時間,就是系統當前時間 + mag-age的值。
1
2
3
4
5
6
7
8
|
header(
"Expires: "
.gmdate(
"D, d M Y H:i:s"
, time()+10000).
' GMT'
);
header(
"Expires: "
.gmdate(
"D, d M Y H:i:s"
, time()-99999).
' GMT'
);
header(
"X-Accel-Expires:5"
);
// 5s
header(
"Cache-Control: no-cache"
);
//no cache
header(
"Cache-Control: no-store"
);
//no cache
header(
"Cache-Control: private"
);
//no cache
header(
"Cache-Control: max-age=10"
);
//cache 10s
setcookie(
'hello'
,
"testaaaa"
);
//no cache
|
注意session使用的時候有坑,可以用下面來設置
1
2
3
|
session_cache_limiter(
"none"
);
session_start();
echo date(
"Y-m-d H:i:s"
,time());
|
可以看一下PHP源代碼中的頭信息 Expires等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
//ext/session/session.c line:1190 左右
// ...
CACHE_LIMITER_FUNC(
private
)
/* {{{ */
{
ADD_HEADER(
"Expires: Thu, 19 Nov 1981 08:52:00 GMT"
);
CACHE_LIMITER(private_no_expire)(TSRMLS_C);
}
/* }}} */
//再到這里3 或者上面幾個 ##默認是nocache
CACHE_LIMITER_FUNC(nocache)
/* {{{ */
{
ADD_HEADER(
"Expires: Thu, 19 Nov 1981 08:52:00 GMT"
);
/* For HTTP/1.1 conforming clients and the rest (MSIE 5) */
ADD_HEADER(
"Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"
);
/* For HTTP/1.0 conforming clients */
ADD_HEADER(
"Pragma: no-cache"
);
}
/* }}} */
//這里2
static
php_session_cache_limiter_t php_session_cache_limiters[] = {
CACHE_LIMITER_ENTRY(
public
)
CACHE_LIMITER_ENTRY(
private
)
CACHE_LIMITER_ENTRY(private_no_expire)
CACHE_LIMITER_ENTRY(nocache)
{0}
};
static
int
php_session_cache_limiter(TSRMLS_D)
/* {{{ */
{
php_session_cache_limiter_t *lim;
if
(PS(cache_limiter)[0] ==
'\0'
)
return
0;
if
(SG(headers_sent)) {
const
char
*output_start_filename = php_output_get_start_filename(TSRMLS_C);
int
output_start_lineno = php_output_get_start_lineno(TSRMLS_C);
if
(output_start_filename) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Cannot send session cache limiter - headers already sent (output started at %s:%d)"
, output_start_filename, output_start_lineno);
}
else
{
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Cannot send session cache limiter - headers already sent"
);
}
return
-2;
}
for
(lim = php_session_cache_limiters; lim->name; lim++) {
if
(!strcasecmp(lim->name, PS(cache_limiter))) {
lim->func(TSRMLS_C);
//這里1
return
0;
}
}
return
-1;
}
|
三、清除緩存
NGINX只在商業版中支持proxy_cache_purge指令清除緩存,開源的ngx_cache_purge模塊只支持單一key的緩存清除。為了實現按目錄清除緩存只能自己開發。
NGINX作為Cache服務器時將資源內容以文件形式進行緩存,緩存元信息存儲於共享內存中,組織成一棵紅黑樹。紅黑樹中的每個節點代表一個Cache元信息。NGINX將Cache Key的HASH值作為紅黑樹節點的KEY。內容緩存文件以該HASH值作為文件名存儲在磁盤上。
NGINX的處理流程簡化描述是這樣的:當請求到達時,根據Cache Key的HASH值在紅黑樹中進行查找。如果找到,並查看相關信息,如果Cache可用,返回相應的Cache文件。否則,則回源抓取。
因為元信息是以Cache Key的HASH值作為Key存儲的,因而紅黑樹中並不能保留Cache Key中有層級關系. 如”/uri/foo”和”/uri/bar”在元信息紅黑樹中完全沒有關系。要實現按照目錄清除緩存,需要將Cache Key中層次關系存儲起來。
可以這樣做,在共享內存中建立一棵目錄樹來存儲層級關系。將Cache Key類比於文件系統中的路徑, 每級路徑存儲為樹中的一個節點。當需要清除某一目錄下的所有緩存時,將該節點子樹的中的所有緩存清除即可。
NGINX和NGINX Plus緩存指南
我們都知道,應用程序和網站的性能是成功的關鍵因素。但是,使您的應用程序或網站表現更好的過程並不總是很清楚。代碼質量和基礎架構當然至關重要,但在很多情況下,您可以通過關注一些非常基本的應用程序交付技術,對應用程序的最終用戶體驗進行大幅改進。一個這樣的例子是通過在你的應用棧中實現和優化緩存。這篇博客文章介紹的技術可以幫助初學者和高級用戶利用NGINX中包含的內容緩存功能獲得更好的性能。
概觀
內容緩存位於客戶端和“原始服務器”之間,並保存其看到的所有內容的副本。如果客戶端請求緩存存儲的內容,它將直接返回內容而不會聯系原始服務器。這可以提高性能,因為內容緩存更接近客戶端,並且更高效地使用應用程序服務器,因為他們無需每次都從頭開始生成頁面。
Web瀏覽器和應用程序服務器之間可能存在多個高速緩存:客戶端的瀏覽器高速緩存,中間緩存,內容交付網絡(CDN)以及位於應用程序服務器前的負載均衡器或反向代理。即使在反向代理/負載平衡器級別,緩存也可以大大提高性能。
舉個例子,去年,我接手了一個緩慢加載的網站的性能調整任務。我注意到的第一件事情是,它花了1秒鍾以生成主頁。經過一些調試之后,我發現由於該頁面被標記為不可緩存,因此它是針對每個請求動態生成的。該頁面本身沒有經常變化,也沒有個性化,所以這不是必需的。作為一個實驗,我標記了負載平衡器緩存5秒的主頁,只是這樣做導致了顯着的改進。第一個字節的時間縮短到幾毫秒,頁面加載速度明顯加快。
NGINX通常作為應用程序堆棧中的反向代理或負載平衡器部署,並具有一整套高速緩存功能。下一節討論如何使用NGINX配置基本緩存。
如何設置和配置基本緩存
只需兩條指令即可啟用基本緩存:proxy_cache_path
和proxy_cache
。該proxy_cache_path
指令設置緩存的路徑和配置,並且該proxy_cache
指令激活它。
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off;
server {
# ...
location / {
proxy_cache my_cache;
proxy_pass http://my_upstream;
}
}
該proxy_cache_path
指令的參數定義了以下設置:
- 緩存的本地磁盤目錄稱為/ path / to / cache /。
levels
在/ path / to / cache /下建立一個兩級目錄層次結構。在單個目錄中有大量文件會降低文件訪問速度,因此我們建議大多數部署使用兩級目錄層次結構。如果levels
參數不包含,NGINX會將所有文件放在同一個目錄中。keys_zone
設置一個共享內存區域用於存儲緩存鍵和元數據(如使用計時器)。在內存中備份密鑰副本使NGINX能夠快速確定請求是否是一個HIT
或一個MISS
不必到磁盤,大大加快檢查。1 MB區域可以存儲大約8,000個密鑰的數據,因此示例中配置的10 MB區域可以存儲大約80,000個密鑰的數據。max_size
設置緩存大小的上限(在本例中為10千兆字節)。它是可選的; 不指定值可以使緩存增長以使用所有可用的磁盤空間。當緩存大小達到限制時,稱為緩存管理器的進程會刪除最近最少使用的文件,以使緩存大小回到最大限度以下。inactive
指定項目在未被訪問的情況下可保留在緩存中的時間。在此示例中,緩存管理器進程會自動從緩存中刪除60分鍾內未請求的文件,而不管其是否已過期。默認值是10分鍾(10m
)。非活動內容與過期內容不同。NGINX不會自動刪除已由緩存控制標頭定義的過期內容(Cache-Control:max-age=120
例如)。只有在指定的時間內沒有訪問過期的(陳舊的)內容時,它才會被刪除inactive
。當訪問過期內容時,NGINX從原始服務器刷新它並重置inactive
定時器。- NGINX首先將寫入緩存的文件寫入臨時存儲區,然后該
use_temp_path=off
指令指示NGINX將它們寫入到將被緩存的相同目錄中。我們建議您將此參數設置off
為避免文件系統之間不必要的數據復制。use_temp_path
在NGINX版本1.7.10和NGINX Plus R6中引入。
最后,該proxy_cache
指令激活緩存與父location
塊的URL匹配的所有內容(在示例中為/)。您也可以proxy_cache
在一個server
塊中包含該指令; 它適用於location
沒有自己的proxy_cache
指令的服務器的所有塊。
當原點關閉時傳送緩存內容
NGINX 內容緩存的一個強大功能是NGINX可以配置為在無法從原始服務器獲取新內容時從緩存中提供陳舊內容。如果高速緩存資源的所有源服務器關閉或暫時繁忙,則可能會發生這種情況。NGINX不是將錯誤傳遞給客戶端,而是從緩存中提供文件的陳舊版本。這為NGINX所代理的服務器提供了額外的容錯級別,並確保服務器故障或流量高峰期的正常運行時間。要啟用此功能,請包含以下proxy_cache_use_stale
指令:
location / {
# ...
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}
通過這個示例配置,如果NGINX 從源服務器收到一個error
,timeout
或任何指定的5xx
錯誤,並且它的緩存中有一個陳舊版本的請求文件,它將傳遞陳舊文件,而不是將錯誤傳遞給客戶端。
微調緩存並提高性能
NGINX具有豐富的可選設置,用於微調緩存的性能。以下是一個激活其中幾個例子的例子:
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off;
server {
# ...
location / {
proxy_cache my_cache;
proxy_cache_revalidate on;
proxy_cache_min_uses 3;
proxy_cache_use_stale error timeout updating http_500 http_502
http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_pass http://my_upstream;
}
}
這些指令配置以下行為:
proxy_cache_revalidate
指示NGINXGET
在刷新源服務器的內容時使用條件請求。如果客戶端請求緩存控制標頭所定義的緩存但過期的項目,NGINX 會將其發送到原始服務器If-Modified-Since
的GET
請求標頭中的字段包含在內。這節省了帶寬,因為服務器只有Last-Modified
在NGINX最初緩存該文件時附加到該文件的頭文件中記錄的時間之后才發送整個項目。proxy_cache_min_uses
設置客戶在NGINX緩存之前必須請求的次數。如果緩存不斷填滿,這很有用,因為它確保只有最常訪問的項目才會添加到緩存中。默認情況下proxy_cache_min_uses
設置為1。- 指令的
updating
參數proxy_cache_use_stale
與啟用指令相結合proxy_cache_background_update
,指示NGINX在客戶端請求從源服務器過期或正在更新的項目時發送陳舊內容。所有更新將在后台完成。所有請求都會返回失效文件,直到完全下載更新的文件。 - 與
proxy_cache_lock
啟用,如果多個客戶端請求的文件不在緩存(電流MISS
),只有第一個這些請求是通過原始服務器允許的。其余請求等待該請求被滿足,然后從緩存中提取文件。如果未proxy_cache_lock
啟用,導致緩存未命中的所有請求將直接轉到原始服務器。
跨多個硬盤分割高速緩存
使用NGINX,無需構建RAID。如果有多個硬盤驅動器,則可以使用NGINX在它們之間分割高速緩存。以下是一個基於請求URI將客戶端平均分配到兩個硬盤驅動器的示例:
proxy_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m
max_size=10g inactive=60m use_temp_path=off;
proxy_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m
max_size=10g inactive=60m use_temp_path=off;
split_clients $request_uri $my_cache {
50% “my_cache_hdd1”;
50% “my_cache_hdd2”;
}
server {
# ...
location / {
proxy_cache $my_cache;
proxy_pass http://my_upstream;
}
}
這兩個proxy_cache_path
指令定義了兩個不同硬盤上的兩個緩存(my_cache_hdd1
和my_cache_hdd2
)。的split_clients
配置塊指定從一半的請求(結果50%
)被緩存在my_cache_hdd1
與另一半中my_cache_hdd2
。基於$request_uri
變量(請求URI)的散列決定了每個請求使用哪個緩存,結果是對給定URI的請求總是緩存在同一個緩存中。
常見問題(FAQ)
本節回答有關NGINX內容緩存的一些常見問題。
NGINX緩存可以進行檢測嗎?
是的,與add_header
指令:
add_header X-Cache-Status $upstream_cache_status;
本示例X-Cache-Status
在響應客戶端時添加HTTP標頭。以下是可能的值$upstream_cache_status
:
MISS
- 在緩存中未找到響應,因此從原始服務器獲取響應。該響應可能已被緩存。BYPASS
- 響應是從原始服務器獲取的,而不是從緩存中提供,因為請求與proxy_cache_bypass
指令匹配(請參閱下面的“我可以通過我的緩存打孔”)。然后可能會緩存響應。EXPIRED
- 緩存中的條目已過期。該響應包含來自原始服務器的新內容。STALE
- 內容陳舊,因為原始服務器沒有正確響應,並且proxy_cache_use_stale
已配置。UPDATING
- 內容陳舊,因為該條目當前正在更新以響應先前的請求並proxy_cache_use_stale updating
進行配置。REVALIDATED
-proxy_cache_revalidate
指令已啟用,NGINX驗證當前緩存內容仍然有效(If-Modified-Since
或If-None-Match
)。HIT
- 響應包含直接來自緩存的有效新鮮內容。
NGINX如何確定是否緩存某些內容?
默認情況下,NGINX尊重Cache-Control
來自原始服務器的標題。它不緩存響應Cache-Control
設置為Private
,No-Cache
或No-Store
或Set-Cookie
在響應頭。NGINX只緩存GET
和HEAD
客戶端請求。您可以覆蓋這些默認值,如下面的答案中所述。
如果proxy_buffering
設置為NGINX不會緩存響應off
。這是on
默認的。
可Cache-Control
頭能視而不見嗎?
是的,與proxy_ignore_headers
指令。例如,使用此配置:
location /images/ {
proxy_cache my_cache;
proxy_ignore_headers Cache-Control;
proxy_cache_valid any 30m;
# ...
}
NGINX忽略/ images /Cache-Control
下所有內容的標題。該指令強制緩存數據到期,如果忽略標題,則是必需的。NGINX不會緩存沒有到期的文件。proxy_cache_valid
Cache-Control
NGINX可以Set-Cookie
在標題中使用a緩存內容嗎?
是的proxy_ignore_headers
,正如前面的回答中所討論的那樣。
NGINX緩存POST
請求可以嗎?
是的,與proxy_cache_methods
指令:
proxy_cache_methods GET HEAD POST;
本示例啟用緩存POST
請求。
NGINX可以緩存動態內容嗎?
是的,只要Cache-Control
標題允許。在短時間內緩存動態內容可以減少原始服務器和數據庫的負載,這可以縮短第一個字節的時間,因為不必為每個請求重新生成頁面。
我可以通過緩存打洞嗎?
是的,與proxy_cache_bypass
指令:
location / {
proxy_cache_bypass $cookie_nocache $arg_nocache;
# ...
}
該指令定義NGINX立即從源服務器請求內容的請求類型,而不是先嘗試在緩存中找到它。這有時被稱為通過緩存“打孔”。在這個例子中,例如,NGINX為具有nocache
cookie或參數的請求執行此操作http://www.example.com/?nocache=true
。NGINX仍然可以為將來未被繞過的請求緩存響應結果。
NGINX使用什么緩存鍵?
該NGINX生成密鑰的缺省形式是類似於以下的MD5哈希NGINX變量:$scheme$proxy_host$request_uri
; 實際使用的算法稍微復雜一些。
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off;
server {
# ...
location / {
proxy_cache my_cache;
proxy_pass http://my_upstream;
}
}
對於此示例配置,緩存密鑰for http://www.example.org/my_image.jpg
計算為md5(“http://my_upstream:80/my_image.jpg”)
。
請注意,$proxy_host
變量用於哈希值而不是實際的主機名(www.example.com
)。$proxy_host
被定義為proxy_pass
指令中指定的代理服務器的名稱和端口。
要更改用作鍵的基礎的變量(或其他詞),請使用該 proxy_cache_key
指令(另請參閱以下問題)。
我可以使用Cookie作為我的緩存鍵的一部分嗎?
是的,緩存密鑰可以配置為任意值,例如:
proxy_cache_key $proxy_host$request_uri$cookie_jessionid;
本示例將JSESSIONID
Cookie 的值合並到緩存鍵中。具有相同URI但具有不同JSESSIONID
值的項目將分別緩存為唯一項目。
NGINX是否使用ETag
標題?
在NGINX 1.7.3和NGINX Plus R5及更高版本中,ETag
頭文件完全受支持If-None-Match
。
NGINX如何處理字節范圍請求?
如果該文件在緩存中是最新的,那么NGINX將確認一個字節范圍請求,並僅將該項目的指定字節提供給客戶端。如果文件沒有被緩存,或者文件已經失效,NGINX從原始服務器下載整個文件。如果請求是針對單個字節范圍的,NGINX一旦在下載流中遇到該范圍,就將該范圍發送給客戶端。如果請求在同一文件中指定了多個字節范圍,則在下載完成時,NGINX會將整個文件傳送到客戶端。
下載完成后,NGINX將整個資源移入緩存中,以便所有將來的字節范圍請求(無論是單個范圍還是多個范圍)都立即從緩存中滿足。
請注意,upstream
服務器必須支持NGINX的字節范圍請求,以響應到該upstream
服務器的字節范圍請求。
NGINX是否支持緩存清除?
NGINX Plus支持選擇性清除緩存文件。如果文件已在源服務器上更新但在NGINX Plus緩存Cache-Control:max-age
中仍然有效(該文件仍然有效,並且指令inactive
參數設置的超時proxy_cache_path
未過期),此功能很有用。借助NGINX Plus的緩存清除功能,該文件可以輕松刪除。有關更多詳細信息,請參閱清除緩存中的內容。
NGINX如何處理Pragma
標題?
在Pragma:no-cache
報頭由客戶加入到繞過所有中間緩存,直接進入到源服務器的請求的內容。NGINX在Pragma
默認情況下不支持標題,但您可以使用以下proxy_cache_bypass
指令配置該功能:
location /images/ {
proxy_cache my_cache;
proxy_cache_bypass $http_pragma;
# ...
}
NGINX是否支持頭文件stale-while-revalidate
和stale-if-error
擴展Cache-Control
?
是的,在NGINX Plus R12和NGINX 1.11.10及更高版本中。這些擴展可以做什么:
- HTTP頭的
stale-while-revalidate
擴展Cache-Control
允許使用陳舊的緩存響應,如果它正在更新。
HTTP頭的stale-if-error
擴展Cache-Control
允許在發生錯誤時使用陳舊的緩存響應。
這些頭具有比低優先級proxy_cache_use_stale
指令如上所述。
NGINX是否支持Vary
標題?
是的,在NGINX Plus R5和NGINX 1.7.7及更高版本中。這是一個很好的Vary
頭部概覽。
安裝Purge模塊
Purge模塊被用來清除緩存
1
2
|
wget http:
//labs.frickle.com/files/ngx_cache_purge-1.2.tar.gz
tar -zxvf ngx_cache_purge-1.2.tar.gz
|
編譯
1
2
3
4
|
./configure \
…… \
--with-http_geoip_module \
--add-module=/usr/local/ngx_cache_purge-1.2
|
四、需要注意的一些問題
設置了之后重啟nginx就可以生效了,這個時候再訪問php的頁面的話,就會被緩存了,可以查看/var/logs/nginx/fastcgi_cache_dir這個目錄下面是有緩存文件的。最后再說明一點,如果更改了緩存目錄的路徑,一定要把緩存的名稱也改掉,后端調用的名稱也同步改掉,如果只改掉了緩存目錄,不改緩存名稱的話,緩存的時候還是會緩存到之前的路徑下面去,但是調用的時候調用的是新的路徑,這個時候就會出現找不到的情況
參考文章
http://www.nginxtips.com/configure-nginx-fastcgi-cache/
http://www.haidx.com/fastcgi-cache-details.html
http://www.just4coding.com/blog/2014/11/01/nginx-purge-directory/
http://weizhifeng.net/nginx-proxy-cache.html
https://www.nginx.com/blog/nginx-caching-guide/#gs.6PdbraI
http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache
https://www.cnxct.com/several-reminder-in-nginx-fastcgi_cache-and-php-session_cache_limiter/
https://rtcamp.com/wordpress-nginx/tutorials/single-site/fastcgi-cache-with-purging/
http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache