最近正將varnish上的cache policy遷移到nginx proxy cache上盛卡,并為后續(xù)使用memorycached緩存做好準(zhǔn)備垫蛆,下文對最近的工作進(jìn)行下梳理和總結(jié)种蘸,歡迎糾錯和探討:
1. 基礎(chǔ)
* 緩存概念
悶著頭皮做了好幾天,將最初的配置模版寫出來了,但是忽略了最重要的一點(diǎn):Basic Principles,所以讓我老大批評了一頓芭毙,并改了不少東西,痛定思痛卸耘,開始看原理:上圖是用戶訪問website流程圖(nginx為proxy)
當(dāng)?shù)谝粋€(gè)用戶(藍(lán))訪問網(wǎng)站退敦,他的請求首先會到NGINX PROXY SERVER,隨后NGNIX發(fā)往后端服務(wù)器(灰),后端會將請求的響應(yīng)首先發(fā)往NGINX鹊奖,由其返回給用戶(藍(lán)色)苛聘,如果這個(gè)響應(yīng)是可以緩存的,則NGINX會保留一份響應(yīng)的副本忠聚,當(dāng)其他用戶(橙色)發(fā)起相同的request請求時(shí)设哗,NGINX會根據(jù)request請求的內(nèi)容是否存在于緩存中,來直接返回給用戶两蟀,不經(jīng)過后端网梢。
這個(gè)場景同樣適用于瀏覽器,CDN赂毯,用于緩存靜態(tài)資源战虏。
* HTTP緩存機(jī)制
后端服務(wù)器會通過響應(yīng)包頭來定義緩存特性:
當(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能識別的緩存特性header姜胖,優(yōu)先級大于上面兩個(gè)header,可以設(shè)置此header淀散,在nginx側(cè)來重新定義緩存特性右莱;
.Etag和Last-Modified是捆綁生成的: 有些場景下,你希望client端的瀏覽器長時(shí)間緩存吧凉,而緩存服務(wù)器只短時(shí)間緩存文件隧出,以至于當(dāng)后端服務(wù)器更新后,緩存服務(wù)器會及時(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ù)端會直接返回304 not modified,這個(gè)驗(yàn)證流程是非持嵩郏快的汛蝙,并且節(jié)省網(wǎng)絡(luò)帶寬;
.如果Cache-Control設(shè)置為public朴肺,則客戶端不會去驗(yàn)證資源的有效性窖剑,將會一直使用直到過期,同時(shí)public也代表資源可以被緩存在web proxy中戈稿;
.如果Cache-Control包含must-revalidate西土,則客戶端每一次訪問請求資源都會去驗(yàn)證緩存是否有更新;
* NGINX都會緩存哪些資源
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 $upstream http://ip:port
???? ???? location / {
???? ???????? ???? proxy_cache my_cache;
???? ???????? ???? proxy_pass $upstream; }
???? ????}
配置項(xiàng)說明:
/path/to/cache : 本地路徑鞍盗,緩存文件存放地址需了;
levels : 默認(rèn)所有緩存文件都放在同一個(gè)/path/to/cache下,從而影響緩存的性能般甲,大部分場景推薦使用2級目錄來存儲緩存文件肋乍;
key_zone : 在共享內(nèi)存中設(shè)置一塊存儲區(qū)域來存放緩存的key和metadata(類似使用次數(shù)),這樣nginx可以快速判斷一個(gè)request是否命中或者未命中緩存敷存,1m可以存儲8000個(gè)key住拭,10m可以存儲80000個(gè)key;
max_size : 最大cache空間,如果不指定滔岳,會使用掉所有disk space,當(dāng)達(dá)到配額后挽牢,會刪除最少使用的cache文件谱煤;
inactive : 未被訪問文件在緩存中保留時(shí)間,本配置中如果60分鐘未被訪問則不論狀態(tài)是否為expired禽拔,緩存控制程序會刪掉文件刘离,默認(rèn)為10分鐘;“需要注意的是睹栖,inactive和expired配置項(xiàng)的含義是不同的硫惕,expired只是緩存過期,但不會被刪除野来,inactive是刪除指定時(shí)間內(nèi)未被訪問的緩存文件”恼除;
use_temp_path : 如果為off,則nginx會將緩存文件直接寫入指定的cache文件中曼氛,而不是使用temp_path存儲豁辉,official建議為off,避免文件在不同文件系統(tǒng)中不必要的拷貝舀患;
proxy_cache : 啟用proxy cache徽级,指定key_zone;
附:緩存和代理中常用的配置項(xiàng)
上文講述了如何配置最基礎(chǔ)的proxy cache,接下來聊浅,會對常用的高級配置項(xiàng)進(jìn)行梳理餐抢。
- proxy_no_cache string;
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努咐,則不會cache苦蒿;例如:proxy_no_cache $cookie_nocache(0) $arg_nocache(1) $arg_comment(0),不會被cache渗稍。`
注:一般會配合proxy_cache_bypass共同使用佩迟;
- proxy_cache_bypass string;
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_key string;
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_methods GET| HEAD|POST...;
Default: proxy_cache_methods GET HEAD;
Context: http, server, location
指定客戶端那些方法被緩存拱燃,默認(rèn)為GET|HEAD秉溉。
- proxy_cache_purge string ...;
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_pass http://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則會被清除,并返回204 response弄跌。注意甲喝,這里是刪除內(nèi)存中的cache key,而不是disk上的cache文件n踔弧2号帧!disk的cache文件是由inactive控制淳玩;
當(dāng)purege request的cache key以通配符*結(jié)束時(shí)直撤,所有匹配到通配符的cache入口的cachekey都會被刪除。
- 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)先級更高的緩存有效時(shí)間:
- “X-Accel-Expires”,設(shè)置響應(yīng)的緩存過期時(shí)間驱敲,以秒為單位;0為不緩存宽闲;
- 如果沒有設(shè)置“X-Accel-Expires” header众眨,則關(guān)于緩存的配置策略可能會在“Expires”或者“Cache-Control” header中;
- 如果header含有“Set-Cookie”,則響應(yīng)不會被緩存容诬,類似的配置可以在“proxy_ignore_header”中可見娩梨;
- header包含“Vary”并且設(shè)置為“*”,則請求不會被緩存览徒,如果“Vary”有具體的值狈定,則對應(yīng)的請求會被緩存;
- proxy_ignore_headers field习蓬;
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)會被緩存枫慷。
- proxy_pass_headers field让蕾;
- proxy_hide_headers field浪规;
Default: —
Context: http, server, location
參考: 1.http://czerasz.com/2015/03/30/nginx-caching-tutorial/ 2.https://www.nginx.com/blog/nginx-caching-guide/ 3.https://www.nginx.com/blog/nginx-high-performance-caching/ 4.http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers 5.http://www.slideshare.net/Nginx/nginx-highperformance-caching 6.https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching 7.http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers 8.https://forum.nginx.org/read.php?2,265703,265704#msg-265704