多級伸縮油缸大腔先伸出來小腔后伸出來
相關(guān)文章
聊聊高并發(fā)系統(tǒng)之HTTP緩存
應(yīng)用多級緩存模式支撐海量讀服務(wù)
應(yīng)用級緩存——《億級流量》
應(yīng)用級緩存示例
應(yīng)用級緩存之緩存使用模式實踐—《億級流量》
Nginx提供了expires、etag、if-modified-since指令來實現(xiàn)瀏覽器緩存控制。
expires
如果我們使用Nginx作為靜態(tài)資源服務(wù)器,那么可以使用expires進行緩存控制。
location /img {
alias /export/img/;
expires 1d;
}
當(dāng)我們訪問靜態(tài)資源時,如,將得到類似如下的響應(yīng)頭。
對于靜態(tài)資源會自動添加ETag,可以通過添加etag off指令禁止生成ETag。如果是靜態(tài)文件,那么Last-Modified值為文件的最后修改時間。Expires是根據(jù)當(dāng)前服務(wù)器系統(tǒng)時間算出來的。如上Nginx配置的計算邏輯(實際計算邏輯比這個多,具體參考官方文檔)。
if (expires == NGX_HTTP_EXPIRES_ACCESS||r->headers_out.last_modified_ time == -1) {
max_age = expires_time;
expires_time += now;
}
if-modified-since
此指令用于指定Nginx如何拿服務(wù)端的Last-Modified和瀏覽器端的if-modified- since時間進行比較,默認“if_modified_since exact”表示精確匹配,也可以使用“if_modified_since _before”表示只要文件的最后修改時間早于或等于瀏覽器端的if-modified-since時間,就返回304。
nginx proxy_pass
使用Nginx作為反向代理時,請求會先進入Nginx,然后Nginx將請求轉(zhuǎn)發(fā)給后端應(yīng)用,如下圖所示。
首先配置upstream。
upstream backend_tomcat {
server 192.168.61.1:9080max_fails=10 fail_timeout=10s weight=5;
}
接著配置location
location = /cache {
proxy_pass https://backend_tomcat/cache$is_args$args;
}
接下來,我們可以通過如https://192.168.61.129/cache?millis=1471349916709訪問Nginx,Nginx會將請求轉(zhuǎn)發(fā)給后端Java應(yīng)用。也就是說Nginx只是做了相關(guān)的轉(zhuǎn)發(fā)(負載均衡),并沒有對請求和響應(yīng)做什么處理。
假設(shè)對后端返回的過期時間需要調(diào)整,可以添加Expires指令到location。
location = /cache {
proxy_pass https://backend_tomcat/cache$is_args$args;
expires 5s;
}
然后再請求相關(guān)的URL,將得到如下響應(yīng)。
過期時間相關(guān)的響應(yīng)頭被Expires指令更改了,但是last-modified是沒有變的。
即使我們更改了緩存過期頭,但Nginx自己沒有對這些內(nèi)容做代理層緩存,每次請求還是要到后端驗證的,假設(shè)在過期時間內(nèi),這些驗證在Nginx這一層驗證就可以了,不需要到后端驗證,這樣可以減少后端很大的壓力。即整體流程如下。
1.瀏覽器發(fā)起請求,首先到Nginx,Nginx根據(jù)URL在Nginx本地查找是否有代理層本地緩存。
2.Nginx沒有找到本地緩存,則訪問后端獲取最新的文檔,并放入到Nginx本地緩存中,返回200狀態(tài)碼和最新的文檔給瀏覽器。
3.Nginx找到本地緩存,首先驗證文檔是否過期(Cache-Control:max-age=5),如果過期,則訪問后端獲取最新的文檔,并放入Nginx本地緩存中,返回200狀態(tài)碼和最新的文檔給瀏覽器多級伸縮油缸;如果文檔沒有過期,即if-modified-since與緩存文檔的last-modified匹配,則返回304狀態(tài)碼給瀏覽器。
內(nèi)容不需要訪問后端,即不需要后端動態(tài)計算/渲染等,直接Nginx代理層就把內(nèi)容返回了,速度更快,內(nèi)容越接近于用戶速度越快。像ApacheTraffic Server、Squid、Varnish、Nginx等技術(shù)都可以用來進行內(nèi)容緩存。還有CDN技術(shù)就是用來加速用戶訪問的。
即用戶首先訪問到全國各地的CDN節(jié)點(使用如ATS、Squid實現(xiàn)),如果CDN沒命中,則會回源到中央Nginx集群,該集群做二級緩存,如果沒有命中緩存(該集群的緩存不是必須的,要根據(jù)實際命中情況等決定),則最后回源到后端應(yīng)用集群。
像我們商品詳情頁的一些服務(wù)就大量使用了Nginx緩存減少回源到后端的請求量,從而提升訪問速度??梢詤⒖肌暗?1章 多級緩存”、“第16章 構(gòu)建需求響應(yīng)式億級商品詳情頁”和“第17章 京東商品詳情頁服務(wù)閉環(huán)實踐”。
Nginx代理層緩存
Nginx代理層緩存配置
HTTP模塊配置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 5124k;
proxy_busy_buffers_size 64k;
proxy_cache_path /export/cache/proxy_cachelevels=1:2 keys_zone=cache:512m inactive=5m max_size=8g use_temp_path=off;
#proxy timeout
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;
proxy_cache_path指令配置多級伸縮油缸:
levels=1:2:表示創(chuàng)建兩級目錄結(jié)構(gòu),緩存目錄的第一級目錄是1個字符,第二級目錄是2個字符,比如/export/cache/proxy_cache/7/3c/,如果將所有文件放在一級目錄下的話,文件量很大,會導(dǎo)致文件訪問慢。
keys_zone=cache:512m :設(shè)置存儲所有緩存key和相關(guān)信息的共享內(nèi)存區(qū),1M大約能存儲8000個key。
inactive=5m :inactive指定被緩存的內(nèi)容多久不被訪問將從緩存中移除,以保證內(nèi)容的新鮮,默認為10分鐘。
max_size=8g :最大緩存閥值,“cache manager”進程會監(jiān)控最大緩存大小,當(dāng)緩存達到該閥值時,該進程將從緩存中移除最近最少訪問的內(nèi)容。
use_temp_path:如果為on,則內(nèi)容首先被寫入臨時文件(proxy_temp_path ),然后重命名到proxy_cache_path指定的目錄;如果設(shè)置為off,則內(nèi)容直接被寫入到proxy_cache_path指定的目錄,如果需要cache建議off,則該特性是1.7.10提供的。
1.location配置
location = /cache {
proxy_cache cache;
proxy_cache_key$scheme$proxy_host$request_uri;
proxy_cache_valid 200 5s;
proxy_passhttps://backend_tomcat/cache$is_args$args;
add_header cache-status$upstream_cache_status;
}
2.緩存相關(guān)配置
proxy_cache:指定使用哪個共享內(nèi)存區(qū)存儲緩存信息。
proxy_cache_key :設(shè)置緩存使用的key,默認為完整的訪問URL,根據(jù)實際情況設(shè)置緩存key。
proxy_cache_valid :為不同的響應(yīng)狀態(tài)碼設(shè)置緩存時間。如果是proxy_cache_valid5s,則200、301、302響應(yīng)都將被緩存。
3.proxy_cache_valid不是唯一設(shè)置緩存時間的,還可以通過如下方式(優(yōu)先級從上到下)。
1.以秒為單位的“X-Accel-Expires”響應(yīng)頭來設(shè)置響應(yīng)緩存時間。
2.如果沒有“X-Accel-Expires”,則可以根據(jù)“Cache-Control”、“Expires”來設(shè)置響應(yīng)緩存時間。
3.否則,使用proxy_cache_valid設(shè)置緩存時間。
如果響應(yīng)頭包含Cache-Control:private/no-cache/no-store、Set-Cookie或者只有一個Vary響應(yīng)頭且其值為*,則響應(yīng)內(nèi)容將不會被緩存??梢允褂胮roxy_ignore_headers來忽略這些響應(yīng)頭。
add_header cache-status $upstream_cache_status在響應(yīng)頭中添加緩存命中的狀態(tài)。
HIT:緩存命中,直接返回緩存中內(nèi)容,不回源到后端。
MISS:緩存未命中,回源到后端獲取最新的內(nèi)容。
EXPIRED:緩存命中但過期了,回源到后端獲取最新的內(nèi)容。
UPDATING:緩存已過期但正在被別的Nginx Worker進程更新,配置了proxy_cache_use_stale updating指令時會存在該狀態(tài)。
STALE:緩存已過期,但因后端服務(wù)出現(xiàn)了問題(比如后端服務(wù)掛了)返回過期的響應(yīng),配置了如proxy_cache_use_stale error timeout指令后會出現(xiàn)該狀態(tài)。
REVALIDATED:啟用proxy_cache_revalidate指令后,當(dāng)緩存內(nèi)容過期時,Nginx通過一次if-modified-since的請求頭去驗證緩存內(nèi)容是否過期,此時會返回該狀態(tài)。
BYPASS:proxy_cache_bypass指令有效時,強制回源到后端獲取內(nèi)容,即使已經(jīng)緩存了。
4.proxy_cache_min_uses
用于控制請求多少次后響應(yīng)才被緩存。默認“proxy_cache_min_uses1;”,如果緩存熱點比較集中、存儲有限,則可以通過修改該參數(shù)來來減少緩存數(shù)量和寫磁盤次數(shù)。
5.proxy_no_cache
用于控制什么情況下響應(yīng)不被緩存。比如配置“proxy_no_cache$args_nocache”,如果帶的nocache參數(shù)值至少有一個不為空或者為0,則響應(yīng)將不被緩存。
6.proxy_cache_bypass
類似于proxy_no_cache,但是,其控制什么情況不使用緩存的內(nèi)容,而是直接到后端獲取最新的內(nèi)容。如果命中,則$upstream_cache_status為BYPASS。
7.proxy_cache_use_stale
當(dāng)對緩存內(nèi)容的過期時間不敏感,或者后端服務(wù)出問題時,即使緩存的內(nèi)容不新鮮也總比返回錯誤給用戶強(類似于托底),此時可以配置該參數(shù),如“proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504”,即如果出現(xiàn)超時、后端連接出錯、500、502、503等錯誤時,則即使緩存內(nèi)容已過期也先返回給用戶,此時$upstream_cache_status為STALE。還有一個updating表示緩存已過期但正在被別的Nginx Worker進程更新,但先返回了過期內(nèi)容,此時$upstream_cache_status為UPDATING。
8.proxy_cache_revalidate
當(dāng)緩存過期后,如果開啟了proxy_cache_revalidate,則會發(fā)出一次if-modified-since或if-none-match條件請求,如果后端返回304,則此時$upstream_cache_status為REVALIDATED,我們將得到兩個好處,節(jié)省帶寬和減少寫磁盤的次數(shù)。
9.proxy_cache_lock
當(dāng)多個客戶端同時請求同一份內(nèi)容時,如果開啟proxy_cache_lock(默認off),則只有一個請求被發(fā)送至后端。其多級伸縮油缸他請求將等待該請求的返回。當(dāng)?shù)谝粋€請求返回后,其他相同請求將從緩存中獲取內(nèi)容返回。當(dāng)?shù)谝粋€請求超過了proxy_cache_lock_timeout超時時間(默認為5s),則其他請求將同時請求到后端來獲取響應(yīng),且響應(yīng)不會被緩存(在1.7.8版本之前是被緩存的)。啟用proxy_cache_lock可以應(yīng)對Dog-pile effect(當(dāng)某個緩存失效時,同時有大量相同的請求沒命中緩存,而同時請求到后端,從而導(dǎo)致后端壓力太大,此時限制一個請求去拿即可)。
proxy_cache_lock_age是1.7.8新添加的,如果在proxy_cache_lock_age指定的時間內(nèi)(默認為5s),最后一個發(fā)送到后端進行新緩存構(gòu)建的請求還沒有完成,則下一個請求將被發(fā)送到后端來構(gòu)建緩存(因為1.7.8版本之后,proxy_cache_lock_timeout超時之后返回的內(nèi)容是不緩存的,需要下一次請求來構(gòu)建響應(yīng)緩存)。
清理緩存
有時緩存的內(nèi)容是錯誤的,需要手工清理,Nginx企業(yè)版提供了purger功能,對于社區(qū)版Nginx可以考慮使用ngx_cache_purge(https://github.com/FRiCKLE/ngx_cache_purge)模塊進行清理緩存。
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge cache$1$is_args$args;
}
該方法要限制其訪問權(quán)限,如只允許內(nèi)網(wǎng)可以訪問或者需要密碼才能訪問。
到此代理層緩存就介紹完了,通過代理層緩存可以解決很多問題,可以參考“第17章 京東商品詳情頁服務(wù)閉環(huán)實踐”。
===========友情推廣===========
京答是京東推出的知識付費產(chǎn)品,京答由提問者、答主、偷聽者三種角色組成交易閉環(huán)。答主為自己設(shè)定提問價格(可修改),提問者需向答主先支付提問金額進行文字提問,答主選擇有價值的問題進行短語音回答,回答后交易完成,答主收到提問者的付款。
歡迎大家來支持下京答。PS:請忽略廣告語,在京答我們一起聊聊網(wǎng)站架構(gòu)~