Nginx緩存原理及配置(頁面緩存)

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ù)器的魯棒性雳灵。

image.png

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
  1. 需要注意的一些問題
    設(shè)置了之后重啟nginx就可以生效了董饰,這個時候再訪問php的頁面的話,就會被緩存了圆米,可以查看/var/logs/nginx/fastcgi_cache_dir這個目錄下面是有緩存文件的卒暂。最后再說明一點,如果更改了緩存目錄的路徑娄帖,一定要把緩存的名稱也改掉也祠,后端調(diào)用的名稱也同步改掉,如果只改掉了緩存目錄近速,不改緩存名稱的話诈嘿,緩存的時候還是會緩存到之前的路徑下面去,但是調(diào)用的時候調(diào)用的是新的路徑削葱,這個時候就會出現(xiàn)找不到的情況奖亚。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市析砸,隨后出現(xiàn)的幾起案子昔字,更是在濱河造成了極大的恐慌,老刑警劉巖首繁,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件作郭,死亡現(xiàn)場離奇詭異陨囊,居然都是意外死亡,警方通過查閱死者的電腦和手機夹攒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門蜘醋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人咏尝,你說我怎么就攤上這事压语。” “怎么了状土?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵无蜂,是天一觀的道長。 經(jīng)常有香客問我蒙谓,道長斥季,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任累驮,我火速辦了婚禮酣倾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谤专。我一直安慰自己躁锡,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布置侍。 她就那樣靜靜地躺著映之,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜡坊。 梳的紋絲不亂的頭發(fā)上杠输,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音秕衙,去河邊找鬼蠢甲。 笑死,一個胖子當(dāng)著我的面吹牛据忘,可吹牛的內(nèi)容都是我干的鹦牛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼勇吊,長吁一口氣:“原來是場噩夢啊……” “哼曼追!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汉规,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拉鹃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鲫忍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膏燕,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年悟民,在試婚紗的時候發(fā)現(xiàn)自己被綠了坝辫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡射亏,死狀恐怖近忙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情智润,我是刑警寧澤及舍,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站窟绷,受9級特大地震影響锯玛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兼蜈,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一攘残、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧为狸,春花似錦歼郭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至漾根,卻和暖如春泰涂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背立叛。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工负敏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秘蛇。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓其做,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赁还。 傳聞我的和親對象是個殘疾皇子妖泄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容