1.Nginx的緩存簡介
nginx的http_proxy模塊,可以實現(xiàn)類似于Squid的緩存功能次坡。Nginx對客戶已經(jīng)訪問過的內(nèi)容在Nginx服務(wù)器本地建立副本呼猪,這樣在一段時間內(nèi)再次訪問該數(shù)據(jù),就不需要通過Nginx服務(wù)器再次向后端服務(wù)器發(fā)出請求砸琅,所以能夠減少Nginx服務(wù)器與后端服務(wù)器之間的網(wǎng)絡(luò)流量,減輕網(wǎng)絡(luò)擁塞轴踱,同時還能減小數(shù)據(jù)傳輸延遲症脂,提高用戶訪問速度。同時淫僻,當(dāng)后端服務(wù)器宕機時诱篷,Nginx服務(wù)器上的副本資源還能夠回應(yīng)相關(guān)的用戶請求,這樣能夠提高后端服務(wù)器的魯棒性雳灵。
2.nginx cache的最基本的配置
nginx.conf
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;//忽略header設(shè)置這些值的內(nèi)容
fastcgi_temp_path /tmp/nginx/fcgi/temp;
vhost配置
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";
#這里cache_key可能有多種設(shè)定:
#商品詳情頁的cache的key:self.busMethod .. '-' .. productId .. '-' .. #apiVersion
#商品列表頁面的cache key:self.busMethod .. '-' .. shopId .. '-' .. listType .. '-' .. cId .. '-' .. sort .. '-' .. page .. '-' .. pageSize
#店鋪商品列表接口cache key:self.busMethod .. '-' .. shopId
#商品評論的列表接口 cache key:self.busMethod .. '-' .. productId .. '-' .. rateType .. '-' .. version .. '-' .. page .. '-' .. pageSize
#推廣領(lǐng)券頁接口 cache key;self.busMethod .. '-' .. couponId .. '-' .. productId
#cache purge
#$1是cache_zone $2是cache_key
location ~ /purge/(.*)/(.*) {
#allow 127.0.0.1;
#allow 10.40.0.0/16;
#deny all;
fastcgi_cache_purge $1 $2;
}
}
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配置
#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"
大概解釋下各個參數(shù)的含義:
fastcgi_cache
該指令用于設(shè)置哪個緩存區(qū)將被使用棕所,zone_name的值為fastcgi_cache_path指令創(chuàng)建的緩存名稱
fastcgi_cache_path
作用域:http
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];
該指令用于設(shè)置緩存文件的存放路徑,示例如下:fastcgi_cache_path /data/nginx/cache levels=1:2 keys_zone=cache_one:100M inactive=1d max_size=10g;
a悯辙、levels:指定了該緩存空間有兩層hash目錄琳省,設(shè)置緩存目錄層數(shù)迎吵,levels=1:2,表示創(chuàng)建兩層目錄緩存针贬,最多創(chuàng)建三層击费。第一層目錄名取fastcgi_cache_key md5的最后一個字符,第二層目錄名取倒數(shù)2-3字符桦他,如:fastcgi_cache_key md5為b7f54b2df7773722d382f4809d65029c蔫巩,則:
levels=1:2為/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
levels=1:2:3為/data/nginx/cache/c/29/650/b7f54b2df7773722d382f4809d65029c
b、keys_zone為這個緩存區(qū)起名為zone_name,500m指代緩存空間為500MB;
c快压、inactive=1d 代表如果緩存文件一天內(nèi)沒有被訪問圆仔,則刪除;
d、max_size=30g代表硬盤緩存最大為30G;
設(shè)置緩存多個磁盤
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;
}
}
將緩存文件放入內(nèi)存中
編輯/etc/fstab 或者 放入 /dev/shm
tmpfs /etc/nginx/cache tmpfs defaults,size=100M 0 0
mount -a
df -ah | grep tmpfs
需要注意的是fastcgi_cache緩存是先寫在fastcgi_temp_path再移到fastcgi_cache_path蔫劣,所以這兩個目錄最好在同一個分區(qū)
荧缘,從0.8.9之后可以在不同的分區(qū),不過還是建議放同一分區(qū).
fastcgi_cache_methods
該指令用于設(shè)置緩存哪些HTTP方法拦宣,默認緩存HTTP GET/HEAD方法截粗。
fastcgi_cache_min_uses
URL經(jīng)過多少次請求將被緩存
fastcgi_cache_valid
reply_code [reply_code ... ] time
為不同的HTTP返回狀態(tài)碼的資源設(shè)置不同的緩存時長。
該指令用于對不同返回狀態(tài)碼的URL設(shè)置不同的緩存時間鸵隧,例如:
proxy_cache_valid 200 302 10m; #為響應(yīng)碼是200和302的資源绸罗,設(shè)置緩存時長為10分鐘
proxy_cache_valid 404 1m; #為響應(yīng)碼是404的資源,設(shè)置的緩存的時長為1分鐘
注意:如果不指定狀態(tài)碼豆瘫,直接指定緩存時間珊蟀,則只有200,301,302狀態(tài)碼會進行緩存。fastcgi_cache_valid 5m;
any 可以指定緩存任何響應(yīng)碼
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 1m;
緩存的參數(shù)也可以在響應(yīng)頭
直接設(shè)置外驱。這些的優(yōu)先級高于緩存時間設(shè)定使用該指令.
Nginx fastcgi_cache在緩存后端fastcgi響應(yīng)時育灸,當(dāng)響應(yīng)里包含“set-cookie”時,不緩存;
當(dāng)響應(yīng)頭包含Expires時昵宇,如果過期時間大于當(dāng)前服務(wù)器時間磅崭,則nginx_cache會緩存該響應(yīng),否則瓦哎,則不緩存;
當(dāng)響應(yīng)頭包含Cache-Control時砸喻,如果Cache-Control參數(shù)值為no-cache、no-store蒋譬、private中任意一個時割岛,則不緩存,如果Cache-Control參數(shù)值為max-age時犯助,會被緩存癣漆,且nginx設(shè)置的cache的過期時間,就是系統(tǒng)當(dāng)前時間 + mag-age的值剂买。
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使用的時候有坑惠爽,可以用下面來設(shè)置
session_cache_limiter("none");
session_start();
echo date("Y-m-d H:i:s",time());
fastcgi_cache_key
該指令用來設(shè)置Web緩存的Key值癌蓖,Nginx根據(jù)Key值MD5緩存。一般根據(jù)host(域名),request_uri(請求的路徑)等變量組合成fastcgi_cache_key疆股。
例如:fastcgi_cache_key "schemerequest_methodhostrequest_uri";
定義fastcgi_cache的key费坊,示例中就以請求的URI作為緩存的key,Nginx會取這個key的md5作為緩存文件旬痹,如果設(shè)置了緩存哈希目錄附井,Nginx會從后往前取相應(yīng)的位數(shù)做為目錄。
注意一定要加上$request_method作為cache key两残,否則如果HEAD類型的先請求會導(dǎo)致后面的GET請求返回為空
fastcgi_temp_path
path [level1 [level2 [level3]]]; 默認為 fastcgi_temp;
該指令用來設(shè)置fastcgi_cache臨時文件目錄
fastcgi_temp_path /spool/nginx/fastcgi_temp 1 2;
a temporary file might look like this:
/spool/nginx/fastcgi_temp/7/45/00000123457
proxy_cache_use_stale
增強站點容錯能力,源站有問題時永毅,nginx可以通過proxy_cache_use_stale指令開啟容錯能力,即使用緩存內(nèi)容來響應(yīng)客戶端的請求人弓。舉個栗子:
location / {
...
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}
如上配置表示沼死,當(dāng)作為cache的NGINX收到源站返回error、timeout或者其他指定的5XX錯誤崔赌,并且在其緩存中有請求文件的陳舊版本意蛀,則會將這些陳舊版本的文件而不是錯誤信息發(fā)送給客戶端。
x-cache
頭健芭,用于調(diào)試
$upstream_response_time為過期時間
緩存命中情況的Nginx變量$upstream_cache_status,表示此請求響應(yīng)來自cache的狀態(tài)县钥,幾種狀態(tài)分別為:
MISS
—— 響應(yīng)在緩存中找不到,所以需要在服務(wù)器中取得慈迈。這個響應(yīng)之后可能會被緩存起來
BYPASS
—— 響應(yīng)來自原始服務(wù)器而不是緩存若贮,因為請求匹配了一個proxy_cache_bypass,這個響應(yīng)之后可能會被緩存起來
EXPIRED
—— 緩存中的某一項過期了痒留,來自原始服務(wù)器的響應(yīng)包含最新的內(nèi)容
STALE
—— 內(nèi)容陳舊是因為原始服務(wù)器不能正確響應(yīng)谴麦。需要配置proxy_cache_use_stale
UPDATING
—— 內(nèi)容過期了,因為相對于之前的請求伸头,響應(yīng)的入口(entry)已經(jīng)更新匾效,并且proxy_cache_use_stale的updating已被設(shè)置
REVALIDATED
—— proxy_cache_revalidate命令被啟用,NGINX檢測得知當(dāng)前的緩存內(nèi)容依然有效(If-Modified-Since或者If-None-Match)
HIT
—— 響應(yīng)包含來自緩存的最新有效的內(nèi)容
http響應(yīng)頭Cache-Control熊锭,當(dāng)在響應(yīng)頭部中Cache-Control被配置為Private弧轧,No-Cache,No-Store或者Set-Cookie碗殷,不允許代理對資源進行緩存。
3.清除緩存
NGINX只在商業(yè)版中支持proxy_cache_purge指令清除緩存速缨,開源的ngx_cache_purge模塊只支持單一key的緩存清除锌妻。為了實現(xiàn)按目錄清除緩存只能自己開發(fā)。
NGINX作為Cache服務(wù)器時將資源內(nèi)容以文件形式進行緩存旬牲,緩存元信息存儲于共享內(nèi)存中仿粹,組織成一棵紅黑樹搁吓。紅黑樹中的每個節(jié)點代表一個Cache元信息。NGINX將Cache Key的HASH值作為紅黑樹節(jié)點的KEY吭历。內(nèi)容緩存文件以該HASH值作為文件名存儲在磁盤上堕仔。
NGINX的處理流程簡化描述是這樣的:當(dāng)請求到達時,根據(jù)Cache Key的HASH值在紅黑樹中進行查找晌区。如果找到摩骨,并查看相關(guān)信息,如果Cache可用朗若,返回相應(yīng)的Cache文件恼五。否則,則回源抓取哭懈。
因為元信息是以Cache Key的HASH值作為Key存儲的灾馒,因而紅黑樹中并不能保留Cache Key中有層級關(guān)系. 如”/uri/foo”和”/uri/bar”在元信息紅黑樹中完全沒有關(guān)系。要實現(xiàn)按照目錄清除緩存遣总,需要將Cache Key中層次關(guān)系存儲起來睬罗。
可以這樣做,在共享內(nèi)存中建立一棵目錄樹來存儲層級關(guān)系旭斥。將Cache Key類比于文件系統(tǒng)中的路徑, 每級路徑存儲為樹中的一個節(jié)點容达。當(dāng)需要清除某一目錄下的所有緩存時,將該節(jié)點子樹的中的所有緩存清除即可琉预。
安裝Purge模塊
Purge模塊被用來清除緩存:
wget http://labs.frickle.com/files/ngx_cache_purge-1.2.tar.gz
tar -zxvf ngx_cache_purge-1.2.tar.gz
編譯
./configure \
…… \
--with-http_geoip_module \
--add-module=/usr/local/ngx_cache_purge-1.2
- 需要注意的一些問題
設(shè)置了之后重啟nginx就可以生效了董饰,這個時候再訪問php的頁面的話,就會被緩存了圆米,可以查看/var/logs/nginx/fastcgi_cache_dir這個目錄下面是有緩存文件的卒暂。最后再說明一點,如果更改了緩存目錄的路徑娄帖,一定要把緩存的名稱也改掉也祠,后端調(diào)用的名稱也同步改掉,如果只改掉了緩存目錄近速,不改緩存名稱的話诈嘿,緩存的時候還是會緩存到之前的路徑下面去,但是調(diào)用的時候調(diào)用的是新的路徑削葱,這個時候就會出現(xiàn)找不到的情況奖亚。