HTTP 協(xié)議的緩存機(jī)制概述

HTTP 協(xié)議的緩存機(jī)制涉及到多個(gè)請求頭字段,而且整個(gè)緩存機(jī)制的細(xì)節(jié)行為也存在各種情況的差異速警,譬如說什么時(shí)候訪問本地緩存不發(fā)送請求叹誉,什么時(shí)候發(fā)送請求查看資源是否更新,獲取 response 什么情況下更新緩存等闷旧。以前我對此一知半解只是籠統(tǒng)的知道一些概念长豁,譬如 Cache-Control 可以控制緩存的時(shí)間和是否需要緩存,但是緩存過期后的行為忙灼,有緩存后瀏覽器是否有 http 請求都不甚了解匠襟。所以特地 google 下,此篇是對此的知識梳理。

協(xié)議概述

什么情況下可以使用本地緩存酸舍?譬如說我們用 get 方式請求了一個(gè)資源 http://mytest.domain.com/static/images/bg.png机错,那么我們下次再請求這個(gè)圖片資源的時(shí)候符合哪些條件可以使用本地緩存呢?

  • url 必須是 http://mytest.domain.com/static/images/bg.png父腕,如果是 http://mytest.domain.com/static/images/bg.png?t=12312321 就會發(fā)起新的請求弱匪,因?yàn)?url 不同。
  • 發(fā)送請求的 method 必須可被緩存璧亮,譬如 get萧诫。
  • 第一次請求 response(即本地緩存)如果有一個(gè) Vary 頭,他的值列出的是一系列 http header枝嘶,第二次請求的請求頭中那些在 Vary 值中所列的頭帘饶,必須和第一次請求相同(具體規(guī)則)。
  • 第二次請求不包含請求頭 Pragma: no-cache
  • 第二次請求不包含請求頭 Cache-Control: no-cache|max-age=0
  • 第一次請求的 response(即本地緩存)不包含 Cache-Control: no-cache
  • 本地緩存沒有過期
  • 或者雖然本地緩存已經(jīng)過期群扶,但是服務(wù)器驗(yàn)證緩存和服務(wù)器資源一致及刻,允許使用本地緩存的情況(即獲得304 response)

注1:上述任何提一個(gè)條件都可以被 cache-control extension 覆蓋

注2:response header中不僅僅可以 Cache-Control: no-cache,還可以 Cache-Control: no-cache="Set-Cookie" 詳見

如何計(jì)算本地緩存是否過期

瀏覽器是通過比較緩存剩余有效時(shí)間和當(dāng)前緩存已存在時(shí)間來判斷的:response_is_fresh = (freshness_lifetime > current_age)竞阐。freshness_lifetime 取值優(yōu)先級次序如下列表所示(排在上面的優(yōu)先級越高):

  1. Cache-Control: s-maxage=xx
  2. Cache-Control: max-age=xx
  3. Expires: xxxxx
  4. 按規(guī)則進(jìn)行計(jì)算(推測)

注1缴饭;如果有多個(gè)重復(fù)的上述頭,那么是非法的骆莹,視作 response(資源)過期

freshness_lifetime 計(jì)算(推測)規(guī)則:

規(guī)范并沒有給出具體的算法颗搂,但是給出了最壞情況(but does impose worst-case constraints on their results),如果 response(資源)有 Last-Modified 頭幕垦,那么推薦用從當(dāng)前到lastmodified這個(gè)時(shí)間段的 10% 作為 freshness_lifetime丢氢,并且 response(資源)的 current_age 如果已經(jīng)超過24小時(shí),必須在這個(gè) response 上加上113 warn-code頭先改。很少有瀏覽器實(shí)現(xiàn)了freshness_lifetime的自助計(jì)算(推測)疚察,所以還是還是鼓勵(lì)給出上述顯式的1 - 3三種情況。

current_age 計(jì)算規(guī)則:

泛泛來說就是 response(資源)在本地的駐足時(shí)間加上網(wǎng)絡(luò)傳輸時(shí)間仇奶,因?yàn)榫W(wǎng)絡(luò)傳輸時(shí)間的計(jì)算有多個(gè)條件貌嫡,規(guī)范實(shí)在看的我頭暈,所以具體計(jì)算規(guī)則詳見規(guī)范

本地緩存過期猜嘱,如何通過服務(wù)器驗(yàn)證緩存的是否依然有效(即304的情況)

首先衅枫,如果第一次的 response(資源)頭中顯示申明了一些禁止緩存的頭(譬如:"no-store" or "no-cache" 等等),就不存在過期不過期的問題朗伶,因?yàn)檫@個(gè)資源不允許緩存弦撩。其次,過期緩存也不一定不可用论皆,如果在斷網(wǎng)或者第二次請求帶上 max-stale 這個(gè)請求頭益楼,那么瀏覽器可以使用過期的緩存(masx-stale 表示在緩存過期后多少時(shí)間內(nèi)瀏覽器依然可以使用緩存)猾漫。碰到過期緩存,瀏覽器可以發(fā)送一個(gè)條件請求(conditional request)感凤。這個(gè)請求的 url 依然是第一次請求的 url悯周,只是會帶上些當(dāng)前資源的一些信息,以供服務(wù)器驗(yàn)證這個(gè)緩存是否依然可用還是需要更新:

  1. response(資源)的 Last-Modified 頭所帶的值會放到條件請求的 If-Modified-Since 頭中陪竿,或者是 If-Unmodified-Since 又或者 If-Range禽翼。
  2. response(資源)的 ETag 頭所帶的值會放到條件請求的 If-None-Match 頭中,或者 If-Match 又或者 If-Range族跛。

服務(wù)器會根據(jù)不同的條件請求頭來驗(yàn)證資源闰挡,具體的行為詳見規(guī)范,這里不細(xì)致展開礁哄。針對條件請求长酗,服務(wù)器返回會有三種情況:

  1. 一個(gè)帶有304 status code 的返回。表示緩存可以被更新和重用桐绒。
  2. 一個(gè)帶有 body 的完整的 response夺脾。表示用這個(gè) response 作為請求的返回,并且視條件可以用這個(gè)完整的 response 替換瀏覽器原有的緩存(此資源)茉继。
  3. 如果返回一個(gè)5xx的 response咧叭,那么瀏覽器可以選擇就顯示這個(gè)5xx的返回,或者使用本地緩存(盡管可能是過期的)- 規(guī)范沒有規(guī)定應(yīng)該選擇哪種處理馒疹,應(yīng)該是取決于瀏覽器的行為佳簸。

如果是一個(gè)304的返回乙墙,規(guī)范說這個(gè)返回可以更新本地緩存颖变,更新策略分三種:

  1. 如果這個(gè)304 response 帶有資源有效性的強(qiáng)驗(yàn)證頭,那么瀏覽器會尋找本地緩存听想,尋找那些帶有同樣強(qiáng)驗(yàn)證頭的緩存腥刹,然后用這個(gè)最新的 response 去更新這些匹配的緩存(同一個(gè)資源可能瀏覽器保存有多份緩存,譬如日期不同等)汉买。
  2. 如果這個(gè)304 response 帶有資源有效性的弱驗(yàn)證頭衔峰,那么瀏覽器同樣會找相匹配的緩存,但是只會更新最新的那條匹配的緩存蛙粘。
  3. 如果這個(gè)304 response 沒有帶有任何資源有效性驗(yàn)證頭垫卤,并且瀏覽器緩存只有一份,并且這份也同樣沒帶有任何資源有效性驗(yàn)證頭出牧,那么瀏覽器就會用這個(gè)304 response穴肘,更新本地緩存。

協(xié)議流程圖

假設(shè)第一次請求一個(gè)資源舔痕,返回 header 里面帶上如下字段:
Cache-Control: max-age=600
Last-Modified: Wed, 28 Aug 2013 10:36:42 GMT
ETag: "124752e0d85461a16e76fbdef2e84fb9"

拋開細(xì)枝末節(jié)的東西评抚,那么第二次請求通常大致流程圖如下:

                  當(dāng)前資源緩存是否過期:response_is_fresh = (freshness_lifetime > current_age)
                                            |
                               -----------------------------------
                              |                                   |        
                              是                                  否
                              |                                   |
                  發(fā)送請求豹缀,帶上請求頭                          從本地緩存中獲取資源(不發(fā)請求)
                  If-Modified-Since: 此資源Last-Modified的值      
                  If-None-Match: 此資源ETag的值
                              |
                  服務(wù)器根據(jù) If-Modified-Since 和 If-None-Match
                  兩個(gè)值判斷資源是否更新過
                              |
                  -------------------------
                 |                         |
                 是                        否
                 |                         |
返回一個(gè) status code:200 的 response    返回一個(gè) status code:304 的 response
response body 里面是請求的資源           response body 為空
                 |                         |
瀏覽器用 response body里面的資源         依然從本地緩存里面獲取資源
替換本地緩存中的資源

特殊情況

當(dāng)你去瀏覽器驗(yàn)證的時(shí)候可能會碰到一些特殊情況,就是緩存有效慨代,但是你刷新瀏覽器依然發(fā)送的條件請求邢笙。其實(shí)是因?yàn)闉g覽器在請求頭中加入了一些料,譬如: Cache-Control: max-age=0侍匙。你刷新的方式可以有很多種氮惯,譬如:按F5,按ctrl+F5想暗,在地址欄按回車等等筐骇。這些不同的行為都會影響瀏覽器發(fā)送請求的行為。這里有一些參考《在瀏覽器地址欄按回車江滨、F5铛纬、Ctrl+F5刷新網(wǎng)頁的區(qū)別

參考資料

rfc7234

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市唬滑,隨后出現(xiàn)的幾起案子告唆,更是在濱河造成了極大的恐慌,老刑警劉巖晶密,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擒悬,死亡現(xiàn)場離奇詭異,居然都是意外死亡稻艰,警方通過查閱死者的電腦和手機(jī)懂牧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尊勿,“玉大人僧凤,你說我怎么就攤上這事≡樱” “怎么了躯保?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長澎语。 經(jīng)常有香客問我途事,道長,這世上最難降的妖魔是什么擅羞? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任尸变,我火速辦了婚禮,結(jié)果婚禮上减俏,老公的妹妹穿的比我還像新娘召烂。我一直安慰自己,他們只是感情好垄懂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布骑晶。 她就那樣靜靜地躺著痛垛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪桶蛔。 梳的紋絲不亂的頭發(fā)上匙头,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天,我揣著相機(jī)與錄音仔雷,去河邊找鬼蹂析。 笑死,一個(gè)胖子當(dāng)著我的面吹牛电抚,可吹牛的內(nèi)容都是我干的蝙叛。 我是一名探鬼主播借帘,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼际起!你這毒婦竟也來了街望?” 一聲冷哼從身側(cè)響起它匕,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后旺韭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酝惧,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡巫财,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了闽瓢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扣讼。...
    茶點(diǎn)故事閱讀 39,769評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弯汰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出曙搬,到底是詐尸還是另有隱情纵装,我是刑警寧澤橡娄,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站瓶籽,受9級特大地震影響埂材,放射性物質(zhì)發(fā)生泄漏俏险。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竣蹦,春花似錦痘括、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喜德,卻和暖如春航棱,著一層夾襖步出監(jiān)牢的瞬間丧诺,已是汗流浹背馁蒂。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工沮脖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留勺届,地道東北人驶俊。 一個(gè)月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像免姿,于是被迫代替她去往敵國和親饼酿。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • http協(xié)議有http0.9胚膊,http1.0故俐,http1.1和http2三個(gè)版本,但是現(xiàn)在瀏覽器使用的是htt...
    一現(xiàn)_閱讀 1,863評論 0 3
  • 一紊婉、概念(載錄于:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436...
    yuantao123434閱讀 8,353評論 6 152
  • Http協(xié)議詳解 標(biāo)簽(空格分隔): Linux 聲明:本片文章非原創(chuàng)药版,內(nèi)容來源于博客園作者M(jìn)IN飛翔的HTTP協(xié)...
    Sivin閱讀 5,223評論 3 82
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)喻犁,斷路器槽片,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 針對瀏覽器的http緩存的分析也算是老生常談了,每隔一段時(shí)間就會冒出一篇不錯(cuò)的文章株汉,其原理也是各大公司面試時(shí)幾乎必...
    全端玩法閱讀 877評論 0 9