1、概論
1.1偎捎、 什么是緩存?
Web緩存是可以自動保存常見文檔副本的HTTP設(shè)備序攘。當(dāng)Web請求抵達(dá)緩存時茴她,如果本地有“已緩存的”副本,就可以從本地存儲設(shè)備而不是原始服務(wù)器中提取這個文檔程奠。因此丈牢,可以這樣理解,緩存攔截了客戶端的請求梦染,代替服務(wù)器端做出響應(yīng)赡麦。
1.2、緩存的作用
使用緩存主要有如下幾個有點:
- 緩存減少了冗余的數(shù)據(jù)傳輸帕识,節(jié)省了你的網(wǎng)絡(luò)費(fèi)用泛粹。
- 緩存緩解了網(wǎng)絡(luò)瓶頸問題。不需要更多的帶寬就能夠更快的加載頁面肮疗。
- 緩存降低了對原始服務(wù)器的要求晶姊。服務(wù)器可以更快地響應(yīng),避免過載的出現(xiàn)伪货。
- 緩存降低了距離時延们衙,因為從較遠(yuǎn)的地方加載頁面會更慢一些钾怔。
1.3、緩存分類
緩存主要分為兩類:
- 私有緩存:緩存存儲在客戶端的存儲器里面蒙挑。
- 公有代理緩存:又稱為緩存代理服務(wù)器或者代理緩存宗侦。它較私有緩存的優(yōu)點是,避免了每個客戶端都需要去服務(wù)器獲取數(shù)據(jù)忆蚀,從而節(jié)省一定的流量矾利。
二者之間的對比如下圖所示:
2、緩存的處理步驟
一個緩存從接收到請求到做出響應(yīng)馋袜,大概可以分為如下7個步驟:
(1)接收——緩存從網(wǎng)絡(luò)中讀取抵達(dá)的請求報文男旗。
(2)解析——緩存對報文進(jìn)行解析,提取出URL和各種首部欣鳖。
(3)查詢——緩存查看是否有本地副本可用察皇,如果沒有,就獲取一份副本(并將其保存在本地)泽台。
(4)新鮮度檢測——緩存查看已緩存副本是否足夠新鮮什荣,如果不是,就詢問服務(wù)器是否有任何更新师痕。
(5)創(chuàng)建響應(yīng)——緩存會用新的首部和已緩存的主體來構(gòu)建一條響應(yīng)報文溃睹。
(6)發(fā)送——緩存通過網(wǎng)絡(luò)將響應(yīng)發(fā)回給客戶端。
(7)日志——緩存可選地創(chuàng)建一個日志文件條目來描述這個事務(wù)胰坟。
下圖描述了緩存中有新鮮緩存時因篇,緩存的處理過程。由此可以看出笔横,這整個過程已經(jīng)與服務(wù)器沒有關(guān)系了:
2.1竞滓、緩存處理流程圖
下圖以簡化的形式顯示了緩存是如何處理請求以獲取一個方法為GET的URL的。
3吹缔、判斷是否新鮮
從上一節(jié)的流程圖可以看出商佑,有兩個工作在緩存的過程中是非常重要的。一個是如何判斷該緩存還是新鮮的厢塘?另一個是驗證緩存副本是否與服務(wù)器原本一致茶没?這兩個工作都是由HTTP報文相關(guān)的首部字段決定的。這一節(jié)我們先考慮第一個問題晚碾,下一節(jié)再探討第二個問題抓半。
3.1、Expires
服務(wù)器使用Expires首部來指定過期日期格嘁。比如說笛求,如果服務(wù)器發(fā)送一個響應(yīng)報文,其中首部有如下字段:
Expires: Mon, 30 Oct 2017, 12:00:00 GMT
這也就說明,該報文會在2017年10月30日的12點整過期探入。在此后到來的響應(yīng)請求狡孔,緩存就會判斷其中的副本不新鮮,需要與服務(wù)器進(jìn)行再驗證蜂嗽。
3.2苗膝、Cache-Control: max-age
使用Expires來判斷是否新鮮雖然可行,但也有一定的問題植旧。那就是它所依賴的是緩存本地的時間荚醒,假設(shè)我所用的緩存是私人緩存,我將自己電腦的時間調(diào)到2200年隆嗅,那么,該副本將在我的有生之年都不會過期侯繁。待我老時胖喳,瀏覽的還是幾十年前的頁面。
實際上Expires是HTTP 1.0協(xié)議引入的贮竟。在HTTP 1.1協(xié)議中引入了Cache-Control: max-age頭部丽焊,解決了Expires所遇到的難題。Expires使用的是絕對時間咕别,而max-age使用的則是相對時間技健。當(dāng)服務(wù)器生產(chǎn)一個響應(yīng)或者再驗證成功時,它會在報文中存儲此刻的時間惰拱,max-age中的時間就是相對該時間的雌贱。比如,如果響應(yīng)報文是此刻生產(chǎn)的偿短,那么下面的語句就是說該緩存會在60秒后過期欣孤,如果你60秒后再來訪問該URL,那么就需要與服務(wù)器進(jìn)行再驗證:
Cache-Control: max-age=60
3.3昔逗、請求報文如何控制新鮮度
上面的內(nèi)容都是針對服務(wù)器的響應(yīng)報文的降传。那么,請求報文有沒有辦法控制新鮮度呢勾怒?或者可以先問這樣一個問題婆排,客戶端是否有必要插手管理緩存的新鮮度呢?
答案是肯定笔链,比如服務(wù)器端使用了Expires字段段只,而我一不小心將時間設(shè)置成了2200年。一天又一天卡乾,無論我怎么請求翼悴,該頁面亙古不變。我依然沒想到是時間設(shè)置的錯誤(我可真笨)。然而鹦赎,有一天谍椅,我不再只是在瀏覽器輸入網(wǎng)址然后敲回車鍵,而是按F5刷新古话,頁面終于奇跡的刷新了雏吭。
請求報文中與緩存新鮮度有關(guān)的也在名為Cache-Control的首部字段中。大概有如下幾種:
3.3.1 max-age
和響應(yīng)報文中的max-age類似陪踩,該值也是一個相對時間杖们。如果當(dāng)前時間減去緩存中存儲的響應(yīng)報文的創(chuàng)建時間超過max-age的值的話,那么緩存就得去和服務(wù)器再驗證了肩狂。
3.3.2 max-stale
stale的意思是不新鮮摘完,max-stale的意思就是說,在多大的范圍內(nèi)傻谁,客戶端還是愿意接受緩存中保存的不新鮮的副本的孝治。也即是說,如果當(dāng)前時間超過了max-age的范圍审磁,但卻沒有超過max-stale值得范圍谈飒,那么緩存副本還是可以代替服務(wù)器做出響應(yīng)的。
3.3.3态蒂、min-fresh
該字段的意思是說杭措,客戶端不希望緩存中副本的新鮮生命周期不低于其創(chuàng)建時間再加上min-fresh指定的時間。如果超過了钾恢,那就從服務(wù)器獲取手素。
4、再驗證
第二個工作就是赘那,緩存是如何與服務(wù)器進(jìn)行交互并再驗證的呢刑桑?HTTP協(xié)議提供了兩種主要的方式:If-Modified-Since:Date和If-None-Match:Etag。它們又被稱為條件驗證募舟。這兩個標(biāo)簽的原理類似祠斧,只是有一點點細(xì)微的差別而已。
整個再驗證的過程和客戶端沒有任何關(guān)系拱礁,僅涉緩存和服務(wù)器雙方琢锋。
- 對于If-Modified-Since:Date的方式,緩存會根據(jù)緩存副本的創(chuàng)建時間來創(chuàng)建If-Modified-Since的值呢灶,這個值可以和服務(wù)器的響應(yīng)首部Last-Modified相配合使用吴超,以此判斷內(nèi)容是否被修改了。
- 如果使用的是If-None-Match:Etag方式鸯乃,那么服務(wù)器會為該文檔提供一個特殊的標(biāo)簽(Etag)鲸阻,當(dāng)緩存去和服務(wù)器溝通時跋涣,發(fā)現(xiàn)服務(wù)器原本的Etag和緩存副本不同,也就認(rèn)為服務(wù)器中的資源被修改了鸟悴。
如果再驗證發(fā)現(xiàn)緩存副本沒有更改陈辱,那么服務(wù)器會回送給客戶端304 Not Modified響應(yīng)∠钢睿客戶端自動重定向到緩存拉取副本沛贪,同時緩存更新相關(guān)首部。如Age震贵、max-age利赋、Etag等。
如果再驗證發(fā)現(xiàn)緩存副本已改變猩系,那么服務(wù)器就會將攜帶新首部的新文檔發(fā)送給緩存媚送,緩存進(jìn)行存取后并對首部進(jìn)行改裝后再以200 OK對客戶端做出響應(yīng)。
如果再驗證發(fā)現(xiàn)服務(wù)器中已沒有此資源時寇甸,服務(wù)器直接向客戶端返回404 Not Found響應(yīng)季希。
注:如果報文中即有If-Modified-Since驗證,又有If-None-Match驗證幽纷,那么只有當(dāng)兩個條件都滿足的情況下才會返回304 Not Modified*響應(yīng)。
5博敬、緩存控制
到這里為止友浸,緩存的處理流程基本上已經(jīng)理清了。然而偏窝,HTTP協(xié)議的能力不僅如此收恢,它還為我們開發(fā)人員提供了強(qiáng)大的控制緩存的機(jī)制,我們可以通過相關(guān)首部控制是否使用緩存祭往,是否一定要再驗證等伦意,這也是由名為Cache-Control的首部字段提供的:
5.1、no-Store
如果請求報文或響應(yīng)報文中含有no-Store時硼补,它會禁止緩存對響應(yīng)進(jìn)行復(fù)制驮肉。
5.2、no-Cache
如果請求報文和響應(yīng)報文中含有no-Cache時已骇,也就是強(qiáng)制了緩存需要與服務(wù)器端進(jìn)行在驗證离钝。
5.3、must-revalidate
這是響應(yīng)報文專用的褪储。
上面說過卵渴,請求報文中可以包含Cache-Control:max-stale標(biāo)簽,它允許緩存提供一定期限的超過了新鮮生命周期的信息鲤竹。而如果響應(yīng)報文使用了must-revalidate浪读,那就意味著,緩存將嚴(yán)格遵守過期信息,只要超過了新鮮生命周期碘橘,就需要和服務(wù)器進(jìn)行再驗證互订。
5.4、only-if-cached
這是請求報文專用的蛹屿。
如果請求報文中有此標(biāo)簽屁奏。那就意味著,客戶端只希望從緩存中讀取資源错负。如果緩存中不存在坟瓢,緩存會返回504 Gateway Timeout響應(yīng)。
5.5犹撒、控制私有和公有
- 如果響應(yīng)報文中含有Cache-Control:public字段折联,那就意味著,服務(wù)器只希望代理緩存對其進(jìn)行復(fù)制识颊。
- 反之诚镰,如果響應(yīng)報文中含有Cache-Control:private字段,那就意味著祥款,服務(wù)器只希望私有緩存對其進(jìn)行復(fù)制清笨。
5.6 補(bǔ)充:Pragma
由于Control-Cache是HTTP 1.1協(xié)議指定的,因此刃跛,為了兼容1.0版本抠艾,客戶端可以發(fā)送包含Pragma:no-Cache首部字段的請求報文。如果其中有Control-Cache:no-Cache并且該字段能夠被理解桨昙,那么Pragma中定義的就會被忽略检号。
6、一種緩存策略決策樹
作為Web服務(wù)器端的開發(fā)者蛙酪,可以參考google提供如下決策樹:
7齐苛、總結(jié)
緩存機(jī)制是HTTP協(xié)議中相對較難的一塊,也是非常重要的一塊桂塞,因此凹蜂,很難說這篇文章沒有任何錯誤,如有錯誤還請指正批評阁危,謝謝炊甲!
參考資料
《HTTP權(quán)威指南》第七章
Google Developers HTTP Cache
rfc7234