流程:
用戶第一次請求,會把返回的文件同時緩存起來,如果再有請求,命中緩存直接從cache返回數(shù)據(jù),省去了fastcgi和php通信處理過程
原理:
NGINX作為Cache服務器時將資源內(nèi)容以文件形式進行緩存,緩存元信息存儲于共享內(nèi)存中,組織成一棵紅黑樹。紅黑樹中的每個節(jié)點代表一個Cache元信息。NGINX將Cache Key(URL 以及相關組合)的HASH值作為紅黑樹節(jié)點的KEY。內(nèi)容緩存文件以該HASH值作為文件名存儲在磁盤上。
緩存過程: ?兩個Nginx 進程參與緩存,cache loader 和 cache manager。cache manager?定期激活檢查緩存文件存在器的狀態(tài)。特別地,當文件存儲器的大小超過 max_size 參數(shù)的值時,把最近最少使用到的數(shù)據(jù)刪除。cache loader?只激活一次,在Nginx啟動之后。它加載先前緩存的數(shù)據(jù)的元信息到共享內(nèi)存區(qū)。一次性在頭一分鐘內(nèi)加載所有的緩存可能會消耗大量的資源和減慢 Nginx 的性能。

fastcgi_cache_path /data/service_data/cache levels=1:2keys_zone=DOMAIN_CACHE:100m max_size=300m inactive=1h;
add_header X-Cache"$upstream_cache_status";
server {
set $hosttype"web";
set $tag0;
set $cache1;if( $request_uri ~ ^([^\?]*)(\?.*)?){
set $key $1;
}if( $http_user_agent ~*'(iPhone|iPod|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry|Windows Phone)') {
set $tag"${tag}1";
}if( $key ~*? ^/((www/fyc(/)?)|(index(/)?)|(index.php)?)$ ){
set $tag"${tag}2";
}if( $tag ="012") {
set $cache0;
set $hosttype"wap";
}if( $key ~*? ^/www/fyc/brifinfo/) {
set $tag"${tag}3";
}if( $http_user_agent ~*'(Guazi/newcar|Guazi/c)') {
set $tag"${tag}4";
}if( $tag ="013") {
set $cache0;
set $hosttype"wap";
}if( $tag ="02"){
set $cache0;
}if( $tag ="03"){
set $cache0;
}if( $tag ="024"){
set $cache0;
set $hosttype"app";
}if( $tag ="034"){
set $cache0;
set $hosttype"app";
}if( $tag ="0124"){
set $cache0;
set $hosttype"app";
}if( $tag ="0134"){
set $cache0;
set $hosttype"app";
}
ocation~* .*\.php?$
{//接口層面set $cache1;if( $http_fpmcache =1){
set $cache0;//如何header 傳fpmcache 1 代表使用緩存}
fastcgi_cache_key $scheme$host$request_uri$request_method;//一定要加上$request_method作為cache key,否則如果HEAD類型的先請求會導致后面的GET請求返回為空,fastcgi_cache DOMAIN_CACHE;
fastcgi_cache_valid20030230110m;
fastcgi_cache_use_stale updating error timeout invalid_header http_500 http_503 http_404;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_cache_bypass $cookie_nocache;
fastcgi_no_cache? $cache;
add_header X-Cache $upstream_cache_status;
add_header X-URI? $key|$request_method|$hosttype|$tag|$cache;
......
}
}

關注狀態(tài)點:
$upstream_cache_status 變量表示此請求響應來自cache的狀態(tài),幾種狀態(tài)分別為:
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 cach
有一些情況會影響到cache的命中 這里需要特別注意
Nginx fastcgi_cache在緩存后端fastcgi響應時,當響應里包含“set-cookie”時,不緩存;
當響應頭包含Expires時,如果過期時間大于當前服務器時間,則nginx_cache會緩存該響應,否則,則不緩存;
當響應頭包含Cache-Control時,如果Cache-Control參數(shù)值為no-cache、no-store、private中任意一個時,則不緩存,如果Cache-Control參數(shù)值為max-age時,會被緩存,且nginx設置的cache的過期時間,就是系統(tǒng)當前時間 + mag-age的值
解決:
加上fastcgi_ignore_headers Cache-Control Expires Set-Cookie;可以解決這個問題
性能對比:
四核邏輯cpu
4G 內(nèi)存
使用Jmeter 壓測
10.16.208.86 (g1-nc-test-v02)
g1-nc-test-v02
線程/sectps接口平均響應cpu
100270/sec253ms60%-70%
150240/sec494ms70%-84%
200281/sec561ms84%左右
300280/sec901ms84%左右
500264/sec1481ms84%左右
使用了fastcgi_cache
四核邏輯cpu
4G 內(nèi)存
使用Jmeter 壓測
10.16.208.87 (g1-nc-test-v01)
g1-nc-test-v01
線程/sectps接口平均響應cpu
100832/sec27ms5%下
1501067/sec39ms5%下
2001294/sec64ms5%下
3001107/sec153ms5%下
500955/sec284ms5%下
以上對比結果: 使用了fastcgi_cache 對QPS 有大概3-5倍的提升速度。(本地單機實測,使用是未使用的10倍左右)。
緩存命中率
遺憾沒有相關命令去查看或者統(tǒng)計緩存命中率,只能通過把$upstream_cache_status 打到日志上統(tǒng)計了。
目前測試命中率大概處于88%-98%之間
1
2
3
4
5
6
7
8
9
10
11
12
13
14//類似shell腳步統(tǒng)計
if["$1"!=''];then
if[ -e"$1"];then
HIT=`cat$1 |grepHIT |wc-l`
ALL=`cat$1 |wc-l`
HIT_RATE=`echo"scale=2;($HIT/$ALL)*100"|bc`
echo"HIT_rate = $HIT_RATE"
else
echo"$1 xxxxxx"
fi
else
xxxxx
fi
清除緩存
NGINX只在商業(yè)版中支持proxy_cache_purge指令清除緩存,開源的ngx_cache_purge模塊只支持單一key的緩存清除。(未測)
缺點:
Fastcgi_cache不會去檢測php是否更新,所以如果有內(nèi)容更新后頁面不會更新
FastCGI Cache不支持分布式緩存,當服務器很多的時候,冗余的浪費將非常嚴重,此外還有數(shù)據(jù)一致性問題,所以它只是一個粗線條的解決方案。
后續(xù)分析下ngx_srcache ? | ? ?lua-resty-cache ?這兩個細粒度相對高的組件。
參考:
https://huoding.com/2014/01/13/321
https://www.ruby-forum.com/topic/3302927
http://jianjye.com/set-nginx-cache-laravel-php-app-5-mins/