HTTP 緩存

每個瀏覽器都自帶了 HTTP 緩存實現(xiàn)功能。您只需要確保每個服務器響應都提供正確的 HTTP 標頭指令厕隧,以指示瀏覽器何時可以緩存響應以及可以緩存多久企量。緩存并重復利用之前獲取的資源是優(yōu)化性能的一個重要方面涵防。

在 http1.0 時代,給客戶端設定緩存方式可通過兩個字段——Pragma和Expires來規(guī)范闹伪。

一,Pragma
有 Pragma:no-cache;表示禁用緩存壮池;

二偏瓤,Expires
exprires是啟用緩存 的方式,與Pragma剛好相對應
正確的格式是 expries:GMT時間格式椰憋;( Expires的值對應一個GMT(格林尼治時間)厅克,比如Mon, 22 Jul 2017 11:12:01 GMT來告訴瀏覽器資源緩存過期時間,如果還沒過該時間點則不發(fā)請求橙依。)

上述兩種方式如果同時存在证舟,Pragma的優(yōu)先級大于Expires。

針對上述的“Expires時間是相對服務器而言票编,無法保證和客戶端時間統(tǒng)一”的問題,http1.1新增了 Cache-Control 來定義緩存過期時間卵渴。

三慧域,Cache-Control

  • 每個資源都可通過 Cache-Control HTTP 標頭定義其緩存策略
  • Cache-Control 指令控制誰在什么條件下可以緩存響應以及可以緩存多久。

從性能優(yōu)化的角度來說浪读,最佳請求是無需與服務器通信的請求:您可以通過響應的本地副本消除所有網絡延遲昔榴,以及避免數(shù)據傳送的流量費用辛藻。為實現(xiàn)此目的,HTTP 規(guī)范允許服務器返回 Cache-Control 指令互订,這些指令控制瀏覽器和其他中間緩存如何緩存各個響應以及緩存多久吱肌。

注:Cache-Control 標頭是在 HTTP/1.1 規(guī)范中定義的,取代了之前用來定義響應緩存策略的標頭(例如 Expires)仰禽。所有現(xiàn)代瀏覽器都支持 Cache-Control氮墨,因此,使用它就夠了吐葵。

注意:若報文中同時出現(xiàn)了 Expires 和 Cache-Control规揪,則以 Cache-Control 為準。
也就是說優(yōu)先級從高到低分別是 Pragma -> Cache-Control -> Expires 温峭。

Cache-Control也是一個通用首部字段猛铅,這意味著它能分別在請求報文和響應報文中使用。在RFC中規(guī)范了 Cache-Control 的格式為:

"Cache-Control" ":" cache-directive

作為請求首部時凤藏,cache-directive 的可選值有:


作為響應首部時奸忽,cache-directive 的可選值有:



Cache-Control 允許自由組合可選值,例如:

Cache-Control: max-age=3600, must-revalidate
定義最佳 Cache-Control 策略

按照以上決策樹為您的應用使用的特定資源或一組資源確定最佳緩存策略揖庄。在理想的情況下栗菜,您的目標應該是在客戶端上緩存盡可能多的響應,緩存盡可能長的時間抠艾,并且為每個響應提供驗證令牌苛萎,以實現(xiàn)高效的重新驗證。

如果客戶端向服務器發(fā)了請求检号,那么是否意味著一定要讀取回該資源的整個實體內容呢腌歉?

我們試著這么想——客戶端上某個資源保存的緩存時間過期了,但這時候其實服務器并沒有更新過這個資源齐苛,如果這個資源數(shù)據量很大翘盖,客戶端要求服務器再把這個東西重新發(fā)一遍過來,是否非常浪費帶寬和時間呢凹蜂?
答案是肯定的馍驯,那么是否有辦法讓服務器知道客戶端現(xiàn)在存有的緩存文件,其實跟自己所有的文件是一致的玛痊,然后直接告訴客戶端說“這東西你直接用緩存里的就可以了汰瘫,我這邊沒更新過呢,就不再傳一次過去了”擂煞。

為了讓客戶端與服務器之間能實現(xiàn)緩存文件是否更新的驗證混弥、提升緩存的復用率,Http1.1新增了幾個首部字段來做這件事情对省。

1.Last-Modified
服務器將資源傳遞給客戶端時蝗拿,會將資源最后更改的時間以“Last-Modified: GMT”的形式加在實體首部上一起返回給客戶端
客戶端會為資源標記上該信息晾捏,下次再次請求時,會把該信息附帶在請求報文中一并帶給服務器去做檢查哀托,若傳遞的時間值與服務器上該資源最終修改時間是一致的惦辛,則說明該資源沒有被修改過,直接返回304狀態(tài)碼仓手,內容為空胖齐,這樣就節(jié)省了傳輸數(shù)據量 。如果兩個時間不一致俗或,則服務器會發(fā)回該資源并返回200狀態(tài)碼市怎,和第一次請求時類似。


這樣保證不向客戶端重復發(fā)出資源辛慰,也保證當服務器有變化時区匠,客戶端能夠得到最新的資源。一個304響應比一個靜態(tài)資源通常小得多帅腌,這樣就節(jié)省了網絡帶寬驰弄。

Last-Modified 存在一定問題,如果在服務器上速客,一個資源被修改了戚篙,但其實際內容根本沒發(fā)生改變,會因為Last-Modified時間匹配不上而返回了整個實體給客戶端(即使客戶端緩存里有個一模一樣的資源)溺职。

2.ETag
為了解決上述Last-Modified可能存在的不準確的問題岔擂,Http1.1還推出了 ETag 實體首部字段。 服務器會通過某種算法浪耘,給資源計算得出一個唯一標志符(比如md5標志)乱灵,在把資源響應給客戶端的時候,會在實體首部加上“ETag: 唯一標識符”一起返回給客戶端七冲。例如:

Etag: "5d8c72a5edda8d6a:3239"

客戶端會保留該 ETag 字段痛倚,并在下一次請求時將其一并帶過去給服務器。服務器只需要比較客戶端傳來的ETag跟自己服務器上該資源的ETag是否一致澜躺,就能很好地判斷資源相對客戶端而言是否被修改過了蝉稳。
如果服務器發(fā)現(xiàn)ETag匹配不上,那么直接以常規(guī)GET 200回包形式將新的資源(當然也包括了新的ETag)發(fā)給客戶端掘鄙;如果ETag是一致的耘戚,則直接返回304知會客戶端直接使用本地緩存即可。

  • 服務器使用 ETag HTTP 標頭傳遞驗證令牌操漠。
  • 驗證令牌可實現(xiàn)高效的資源更新檢查:資源未發(fā)生變化時不會傳送任何數(shù)據收津。

這正是驗證令牌(在 ETag 標頭中指定)旨在解決的問題。服務器生成并返回的隨機令牌通常是文件內容的哈希值或某個其他指紋∨蠼兀客戶端不需要了解指紋是如何生成的,只需在下一次請求時將其發(fā)送至服務器吧黄。如果指紋仍然相同部服,則表示資源未發(fā)生變化,您就可以跳過下載拗慨。


在上例中廓八,客戶端自動在“If-None-Match” HTTP 請求標頭內提供 ETag 令牌。服務器根據當前資源核對令牌赵抢。如果它未發(fā)生變化剧蹂,服務器將返回“304 Not Modified”響應,告知瀏覽器緩存中的響應未發(fā)生變化烦却,可以再延用 120 秒宠叼。請注意,您不必再次下載響應其爵,這節(jié)約了時間和帶寬冒冬。

作為網絡開發(fā)者,您如何利用高效的重新驗證摩渺?瀏覽器會替我們完成所有工作:它會自動檢測之前是否指定了驗證令牌简烤,它會將驗證令牌追加到發(fā)出的請求上,并且它會根據從服務器接收的響應在必要時更新緩存時間戳摇幻。我們唯一要做的就是確保服務器提供必要的 ETag 令牌横侦。檢查您的服務器文檔中有無必要的配置標志。

不過绰姻,如果您想更新或廢棄緩存的響應枉侧,該怎么辦?

注意:假定您已告訴訪問者將某個 CSS 樣式表緩存長達 24 小時 (max-age=86400)龙宏,但設計人員剛剛提交了一個您希望所有用戶都能使用的更新棵逊。您該如何通知擁有現(xiàn)在“已過時”的 CSS 緩存副本的所有訪問者更新其緩存?在不更改資源網址的情況下银酗,您做不到辆影。

瀏覽器緩存響應后,緩存的版本將一直使用到過期(由 max-age 或 expires 決定)黍特,或一直使用到由于某種其他原因從緩存中刪除蛙讥,例如用戶清除了瀏覽器緩存。因此灭衷,構建網頁時次慢,不同的用戶可能最終使用的是文件的不同版本;剛獲取了資源的用戶將使用新版本的響應,而緩存了早期(但仍有效)副本的用戶將使用舊版本的響應迫像。

所以劈愚,如何才能魚和熊掌兼得:客戶端緩存和快速更新?

您可以在資源內容發(fā)生變化時更改它的網址闻妓,強制用戶下載新響應菌羽。通常情況下,可以通過在文件名中嵌入文件的指紋或版本號來實現(xiàn) - 例如 style.x234dff.css由缆。


因為能夠定義每個資源的緩存策略注祖,所以您可以定義“緩存層次結構”,這樣不但可以控制每個響應的緩存時間均唉,還可以控制訪問者看到新版本的速度是晨。為了進行說明,我們一起分析一下上面的示例:

  • HTML 被標記為“no-cache”舔箭,這意味著瀏覽器在每次請求時都始終會重新驗證文檔罩缴,并在內容變化時獲取最新版本。此外层扶,在 HTML 標記內靴庆,您在 CSS 和 JavaScript 資產的網址中嵌入指紋:如果這些文件的內容發(fā)生變化,網頁的 HTML 也會隨之改變怒医,并會下載 HTML 響應的新副本炉抒。
  • 允許瀏覽器和中間緩存(例如 CDN)緩存 CSS,并將 CSS 設置為 1 年后到期稚叹。請注意焰薄,您可以放心地使用 1 年的“遠期過期”,因為您在文件名中嵌入了文件的指紋:CSS 更新時網址也會隨之變化扒袖。
  • JavaScript 同樣設置為 1 年后到期塞茅,但標記為 private,這或許是因為它包含的某些用戶私人數(shù)據是 CDN 不應緩存的季率。
  • 圖像緩存時不包含版本或唯一指紋野瘦,并設置為 1 天后到期。

您可以組合使用 ETag飒泻、Cache-Control 和唯一網址來實現(xiàn)一舉多得:較長的過期時間鞭光、控制可以緩存響應的位置以及隨需更新。

不存在什么最佳緩存策略泞遗。

您需要根據通信模式惰许、提供的數(shù)據類型以及應用特定的數(shù)據更新要求,為每個資源定義和配置合適的設置史辙,以及整體的“緩存層次結構”汹买。

在制定緩存策略時佩伤,您需要牢記下面這些技巧和方法:

  • 使用一致的網址:如果您在不同的網址上提供相同的內容,將會多次獲取和存儲這些內容晦毙。提示:請注意生巡,網址區(qū)分大小寫
  • 確保服務器提供驗證令牌 (ETag):有了驗證令牌见妒,當服務器上的資源未發(fā)生變化時障斋,就不需要傳送相同的字節(jié)。
  • 為每個資源確定最佳緩存周期:不同的資源可能有不同的更新要求徐鹤。為每個資源審核并確定合適的 max-age。
  • 確定最適合您的網站的緩存層次結構:您可以通過為 HTML 文檔組合使用包含內容指紋的資源網址和短時間或 no-cache 周期邀层,來控制客戶端獲取更新的速度返敬。
  • 最大限度減少攪動:某些資源的更新比其他資源頻繁。如果資源的特定部分(例如 JavaScript 函數(shù)或 CSS 樣式集)會經常更新寥院,可以考慮將其代碼作為單獨的文件提供劲赠。這樣一來,每次獲取更新時秸谢,其余內容(例如變化不是很頻繁的內容庫代碼)可以從緩存獲取凛澎,從而最大限度減少下載的內容大小。

參考資料
HTTP 緩存

HTTP緩存控制小結

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末估蹄,一起剝皮案震驚了整個濱河市塑煎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌臭蚁,老刑警劉巖最铁,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異垮兑,居然都是意外死亡冷尉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門系枪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雀哨,“玉大人,你說我怎么就攤上這事私爷∥砉祝” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵衬浑,是天一觀的道長垢村。 經常有香客問我,道長嚎卫,這世上最難降的妖魔是什么嘉栓? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任宏榕,我火速辦了婚禮,結果婚禮上侵佃,老公的妹妹穿的比我還像新娘麻昼。我一直安慰自己,他們只是感情好馋辈,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布抚芦。 她就那樣靜靜地躺著,像睡著了一般迈螟。 火紅的嫁衣襯著肌膚如雪叉抡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天答毫,我揣著相機與錄音褥民,去河邊找鬼。 笑死洗搂,一個胖子當著我的面吹牛消返,可吹牛的內容都是我干的。 我是一名探鬼主播耘拇,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼撵颊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惫叛?” 一聲冷哼從身側響起倡勇,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘉涌,沒想到半個月后译隘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡洛心,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年固耘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片词身。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡厅目,死狀恐怖,靈堂內的尸體忽然破棺而出法严,到底是詐尸還是另有隱情损敷,我是刑警寧澤肄扎,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布无牵,位于F島的核電站,受9級特大地震影響罕模,放射性物質發(fā)生泄漏溯街。R本人自食惡果不足惜诱桂,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一洋丐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挥等,春花似錦友绝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辞槐,卻和暖如春掷漱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背榄檬。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工卜范, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丙号。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像缰冤,于是被迫代替她去往敵國和親犬缨。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容

  • 本文內容大多參考《圖解HTTP》一書 一. 認識代理服務器 所以講緩存為什么要先扯代理服務器棉浸?別急怀薛,讓我們看一下一...
    流光號船長閱讀 1,921評論 0 10
  • 網絡特有的延遲以及數(shù)據傳輸?shù)某杀荆萍s互聯(lián)網快速獲取Web資源迷郑。為此枝恋,HTTP協(xié)議引入緩存以空間換時間,使瀏覽器緩...
    大頭8086閱讀 3,066評論 2 12
  • HTTP 緩存 摘自谷歌開發(fā)文檔 通過網絡獲取內容既速度緩慢又開銷巨大嗡害。較大的響應需要在客戶端與服務器之間進行多次...
    有涯逐無涯閱讀 321評論 0 1
  • 全文轉自HTTP 緩存 通過網絡獲取內容既速度緩慢又開銷巨大焚碌。較大的響應需要在客戶端與服務器之間進行多次往返通信,...
    Addy_Zhou閱讀 347評論 0 0
  • 這段日子,高中同學都在空間里吐槽大學有多么多么的辛苦叹螟,有多么多么的可怕鹃骂。并且表示對高中的想念。對此罢绽,錢鐘書先生...
    風如斯閱讀 586評論 2 2