轉(zhuǎn)載來自:http://www.reibang.com/p/625c2b15dad5
圖一:nginx緩存原理
悶著頭皮做了好幾天秩贰,將最初的配置模版寫出來了躺率,但是忽略了最重要的一點(diǎn):Basic Principles,所以讓我老大批評(píng)了一頓揖膜,并改了不少東西嗦玖,痛定思痛浩销,開始看原理:上圖是用戶訪問website流程圖(nginx為proxy)
當(dāng)?shù)谝粋€(gè)用戶(藍(lán))訪問網(wǎng)站购披,他的請求首先會(huì)到NGINX PROXY SERVER,隨后NGNIX發(fā)往后端服務(wù)器(灰),后端會(huì)將請求的響應(yīng)首先發(fā)往NGINX痊远,由其返回給用戶(藍(lán)色)垮抗,如果這個(gè)響應(yīng)是可以緩存的,則NGINX會(huì)保留一份響應(yīng)的副本碧聪,當(dāng)其他用戶(橙色)發(fā)起相同的request請求時(shí)冒版,NGINX會(huì)根據(jù)request請求的內(nèi)容是否存在于緩存中,來直接返回給用戶逞姿,不經(jīng)過后端辞嗡。
這個(gè)場景同樣適用于瀏覽器,CDN滞造,用于緩存靜態(tài)資源续室。
* HTTP緩存機(jī)制
后端服務(wù)器會(huì)通過響應(yīng)包頭來定義緩存特性:
圖二:Origin Server定義的緩存特性
當(dāng)然,緩存服務(wù)器可以通過設(shè)置一些參數(shù)來忽略或者重寫后端服務(wù)器的緩存特性谒养,但后端服務(wù)器的緩存特性也是極其重要的挺狰。
.Expires: 最原始的配置策略,即設(shè)置過期時(shí)間买窟,但使用效率低下丰泊,目前絕大部分已經(jīng)被Cache-Control(有興趣的可以去看下http1.0和http1.1);
.Cache-Control:定義緩存資源屬性是private或者是public蔑祟,并且設(shè)置緩存多久后過期趁耗,本例中,屬性為public疆虚,60秒過期苛败;
.X-Accel-Expires: 只有nginx能識(shí)別的緩存特性header,優(yōu)先級(jí)大于上面兩個(gè)header径簿,可以設(shè)置此header罢屈,在nginx側(cè)來重新定義緩存特性;
.Etag和Last-Modified是捆綁生成的: 有些場景下篇亭,你希望client端的瀏覽器長時(shí)間緩存缠捌,而緩存服務(wù)器只短時(shí)間緩存文件,以至于當(dāng)后端服務(wù)器更新后,緩存服務(wù)器會(huì)及時(shí)同步曼月,我們就可以使用最后兩個(gè)header谊却,Last-Modified表示最后修改時(shí)間,并聲明一個(gè)ETag(哈希值)哑芹,做為緩存內(nèi)容的標(biāo)簽炎辨,具有唯一性;客戶端訪問請求帶有If?Modified?Since或者If?None?Match header,并申明自己的客戶端帶有靜態(tài)緩存文件,以及文件修改日期和ETag值聪姿,如果服務(wù)器端的版本和Etag值與客戶端一致碴萧,則服務(wù)端會(huì)直接返回304 not modified,這個(gè)驗(yàn)證流程是非衬┕海快的破喻,并且節(jié)省網(wǎng)絡(luò)帶寬;
.如果Cache-Control設(shè)置為public盟榴,則客戶端不會(huì)去驗(yàn)證資源的有效性曹质,將會(huì)一直使用直到過期,同時(shí)public也代表資源可以被緩存在web proxy中曹货;
.如果Cache-Control包含must-revalidate咆繁,則客戶端每一次訪問請求資源都會(huì)去驗(yàn)證緩存是否有更新;
* NGINX都會(huì)緩存哪些資源
2. 最佳實(shí)踐
首先看下nginx 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 {
set $upstreamhttp://ip:port
location / {
proxy_cachemy_cache;
proxy_pass$upstream; }
}
配置項(xiàng)說明:
/path/to/cache : 本地路徑顶籽,緩存文件存放地址;
levels : 默認(rèn)所有緩存文件都放在同一個(gè)/path/to/cache下银觅,從而影響緩存的性能礼饱,大部分場景推薦使用2級(jí)目錄來存儲(chǔ)緩存文件;
key_zone : 在共享內(nèi)存中設(shè)置一塊存儲(chǔ)區(qū)域來存放緩存的key和metadata(類似使用次數(shù))究驴,這樣nginx可以快速判斷一個(gè)request是否命中或者未命中緩存镊绪,1m可以存儲(chǔ)8000個(gè)key,10m可以存儲(chǔ)80000個(gè)key洒忧;用在內(nèi)存的
max_size : 最大cache空間蝴韭,如果不指定,會(huì)使用掉所有disk space熙侍,當(dāng)達(dá)到配額后榄鉴,會(huì)刪除最少使用的cache文件;用在磁盤的
inactive : 未被訪問文件在緩存中保留時(shí)間蛉抓,本配置中如果60分鐘未被訪問則不論狀態(tài)是否為expired庆尘,緩存控制程序會(huì)刪掉文件乳愉,默認(rèn)為10分鐘凌停;“需要注意的是,inactive和expired配置項(xiàng)的含義是不同的囤屹,expired只是緩存過期笑跛,但不會(huì)被刪除付魔,inactive是刪除指定時(shí)間內(nèi)未被訪問的緩存文件”聊品;
use_temp_path : 如果為off,則nginx會(huì)將緩存文件直接寫入指定的cache文件中几苍,而不是使用temp_path存儲(chǔ)翻屈,official建議為off,避免文件在不同文件系統(tǒng)中不必要的拷貝擦剑;如果為on妖胀,那么會(huì)先保存在temp_path,然后再移動(dòng)到cache空間惠勒。
proxy_cache : 啟用proxy cache赚抡,指定key_zone;
附:緩存和代理中常用的配置項(xiàng)
上文講述了如何配置最基礎(chǔ)的proxy cache,接下來纠屋,會(huì)對常用的高級(jí)配置項(xiàng)進(jìn)行梳理涂臣。
proxy_no_cachestring;
Default: —
Context: http , server , location
config example:
proxy_no_cache$cookie_nocache? $arg_nocache? $arg_comment;
proxy_no_cache$http_pragma? ? $http_authorization;
$cookie_nocache $arg_nocache...皆為變量,可以根據(jù)你訪問的匹配策略來設(shè)置售担,其值只有2類赁遗,0和非0;
訪問匹配策略例如:
if ($request_uri ~ ^/(login|register|password\/reset)/) { set $cookie_nocache 1; }
如果在此鏈?zhǔn)脚渲弥校灰幸粋€(gè)值不為0族铆,則不會(huì)cache岩四;例如:proxy_no_cache $cookie_nocache(0) $arg_nocache(1) $arg_comment(0),不會(huì)被cache哥攘。`
注:一般會(huì)配合proxy_cache_bypass共同使用剖煌;
proxy_cache_bypassstring;
Default: —
Context: http , server , location
config example:
proxy_cache_bypass$cookie_nocache $arg_nocache$arg_comment;
proxy_cache_bypass$http_pragma? ? $http_authorization;
定義在哪些情況下不從cache讀取,直接從backend獲取資源逝淹;配置方式同proxy_no_cache耕姊。
proxy_cache_keystring;
Default: proxy_cache_key $scheme$proxy_host$request_uri;
Context: http, server, location
自定義cache key,例如:
proxy_cache_key "$host$request_uri $cookie_user";
默認(rèn)值為:
proxy_cache_key $scheme$proxy_host$uri$is_args$args;
proxy_cache_methodsGET| HEAD|POST...;
Default: proxy_cache_methods GET HEAD;
Context: http, server, location
指定客戶端那些方法被緩存栅葡,默認(rèn)為GET|HEAD茉兰。
proxy_cache_purgestring ...;
Default: —
Context: http, server, location
config example:
proxy_cache_path /data/nginx/cache keys_zone=cache_zone:10m;
map $request_method $purge_method {
PURGE? 1;
default 0;
}
server {
...
location / {
proxy_passhttp://backend;
proxy_cache cache_zone;
proxy_cache_key $uri;
proxy_cache_purge $purge_method;
}
}
定義緩存清除場景,同proxy_no_cache欣簇,proxy_cache_bypass鏈?zhǔn)脚渲梅绞焦媪常灰忠粋€(gè)不為0,則清除對應(yīng)的cache key則會(huì)被清除醉蚁,并返回204 response燃辖。注意,這里是刪除內(nèi)存中的cache key网棍,而不是disk上的cache文件G辍!!disk的cache文件是由inactive控制氏身;
當(dāng)purege request的cache key以通配符*結(jié)束時(shí)巍棱,所有匹配到通配符的cache入口的cachekey都會(huì)被刪除。
proxy_cache_valid*[code...] time *;
Default: —
Context: http, server, location
設(shè)置不同相應(yīng)碼的緩存時(shí)間蛋欣,當(dāng)不指定響應(yīng)碼的時(shí)候航徙,例如
proxy_cache_valid 5m;
只對響應(yīng)碼為200,301陷虎,302的訪問請求資源設(shè)置緩存時(shí)間到踏,此外可以個(gè)性化定制,例如:
proxy_cache_valid 200 302 10m; proxy_cache_valid 301 1h; proxy_cache_valid 404 1m; proxy_cache_valid any 1m;
此外尚猿,還可以在相應(yīng)header里設(shè)置優(yōu)先級(jí)更高的緩存有效時(shí)間:
“X-Accel-Expires”,設(shè)置響應(yīng)的緩存過期時(shí)間窝稿,以秒為單位;0為不緩存凿掂;
如果沒有設(shè)置“X-Accel-Expires” header伴榔,則關(guān)于緩存的配置策略可能會(huì)在“Expires”或者“Cache-Control” header中;
如果header含有“Set-Cookie”,則響應(yīng)不會(huì)被緩存庄萎,類似的配置可以在“proxy_ignore_header”中可見踪少;
header包含“Vary”并且設(shè)置為“*”,則請求不會(huì)被緩存糠涛,如果“Vary”有具體的值援奢,則對應(yīng)的請求會(huì)被緩存;
proxy_ignore_headersfield忍捡;
Default: —
Context: http, server, location
不緩存包含在field的響應(yīng)header萝究,可以設(shè)置的值有:“X-Accel-Redirect”, “X-Accel-Expires”, “X-Accel-Limit-Rate”,“X-Accel-Buffering”, “X-Accel-Charset”, “Expires”, “Cache-Control”, “Set-Cookie” (0.8.44), and “Vary”锉罐。
如果上述的header field沒有設(shè)置為忽略,則header filed中有“X-Accel-Expires”, “Expires”, “Cache-Control”, “Set-Cookie”, and “Vary”的話绕娘,響應(yīng)會(huì)被緩存脓规。
proxy_pass_headersfield;
proxy_hide_headersfield险领;
Default: —
Context: http, server, location
upstream imooc {
? ? ? ? server 116.62.103.228:8001;
? ? ? ? server 116.62.103.228:8002;
? ? ? ? server 116.62.103.228:8003;
? ? }
? ? proxy_cache_path /opt/app/cache levels=1:2 keys_zone=imooc_cache:10m max_size=10g inactive=60m use_temp_path=off;
server {
? ? listen? ? ? 80;
? ? server_name? web01.fadewalk.com;
? ? access_log? /var/log/nginx/test_proxy.access.log? main;
? ? location / {
? ? ? ? proxy_cache imooc_cache;
? ? ? ? proxy_pass http://imooc;
? ? ? ? proxy_cache_valid 200 304 12h;?? #200? 304 狀態(tài)碼的緩存12小時(shí)
? ? ? ? proxy_cache_valid any 10m;?? #其他狀態(tài)碼緩存10分鐘
? ? ? ? proxy_cache_key $host$uri$is_args$args;?? #用于生成緩存文件的名字
? ? ? ? add_header? Nginx-Cache "$upstream_cache_status";? #用于返回給客戶端侨舆,查看客戶端請求的內(nèi)容,是否從緩存中獲取的
? ? ? ? proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;?? #當(dāng)后臺(tái)服務(wù)器返回 error timeout invalid_header http_500 http_502 http_503 http_504這些其中一個(gè)錯(cuò)誤绢陌,就會(huì)切換到另外一臺(tái)后端服務(wù)器挨下,進(jìn)行請求
? ? ? ? include proxy_params;
? ? }
}
讓某些請求不進(jìn)行緩存
if ($request_uri ~ ^/(login|register|password\/reset)/)
{
set $cookie_nocache 1;
}
server {
}
如何查看是否命中緩存
add_header Nging-Cache "$upstream_cache_status";
upstream_cache_status
當(dāng)我們沒有緩存的時(shí)候,我們可以看到應(yīng)答會(huì)是MISS:
MISS
如果緩存了:
HIT
通過設(shè)置log_format,打印日志分析
現(xiàn)在nginx.conf中加入新的配置項(xiàng):
nginx.conf
此時(shí)我們怒刷前端頁面脐湾,會(huì)發(fā)現(xiàn)后端日志如下:
access.log
proxy_cache_path /data/cache levels=1:2 keys_zone=whsir_com:10m max_size=10g inactive=60m use_temp_path=on;
location ~ /purge(/.*) {
? ? ? ? ? ? proxy_cache_purge whsir_com $host$1$is_args$args;
? ? ? ? }
清除指定的緩存文件
http://192.168.1.2/purge/1.html?? 清除1.html這個(gè)文件
http://192.168.1.2/purge/www/1.html?? 清除1.html這個(gè)文件