大型網(wǎng)站必備,徹底理解Http的緩存機(jī)制!

概述

瀏覽器的緩存機(jī)制也就是我們說(shuō)的HTTP緩存機(jī)制,其機(jī)制是根據(jù)HTTP報(bào)文的緩存標(biāo)識(shí)進(jìn)行的,所以在分析瀏覽器緩存機(jī)制之前,我們先使用圖文簡(jiǎn)單介紹一下HTTP報(bào)文,HTTP報(bào)文分為兩種:

  • HTTP請(qǐng)求(Request)報(bào)文,報(bào)文格式為:請(qǐng)求行 – HTTP頭(通用信息頭,請(qǐng)求頭,實(shí)體頭) – 請(qǐng)求報(bào)文主體(只有POST才有報(bào)文主體),如下圖
image
image
  • HTTP 響應(yīng)(Response)報(bào)文,報(bào)文格式為:
image
image

以上的概念在這里我們不做多講解,只簡(jiǎn)單介紹,有興趣的童鞋可以自行研究。

緩存過(guò)程分析

瀏覽器與服務(wù)器通信的方式為應(yīng)答模式,即,瀏覽器發(fā)起 HTTP 請(qǐng)求 –> 服務(wù)器響應(yīng)該請(qǐng)求。

那么瀏覽器第一次向服務(wù)器發(fā)起該請(qǐng)求后拿到請(qǐng)求結(jié)果,會(huì)根據(jù)響應(yīng)報(bào)文中 HTTP 頭的緩存標(biāo)識(shí),決定是否緩存結(jié)果,是則將請(qǐng)求結(jié)果和緩存標(biāo)識(shí)存入瀏覽器緩存中,簡(jiǎn)單的過(guò)程如下圖:

image

由上圖我們可以知道:

  • 瀏覽器每次發(fā)起請(qǐng)求,都會(huì)先在瀏覽器緩存中查找該請(qǐng)求的結(jié)果以及緩存標(biāo)識(shí)。

  • 瀏覽器每次拿到返回的請(qǐng)求結(jié)果都會(huì)將該結(jié)果和緩存標(biāo)識(shí)存入瀏覽器緩存中。

以上兩點(diǎn)結(jié)論就是瀏覽器緩存機(jī)制的關(guān)鍵,他確保了每個(gè)請(qǐng)求的緩存存入與讀取,只要我們?cè)倮斫鉃g覽器緩存的使用規(guī)則,那么所有的問(wèn)題就迎刃而解了,本文也將圍繞著這點(diǎn)進(jìn)行詳細(xì)分析。

為了方便大家理解,這里我們根據(jù)是否需要向服務(wù)器重新發(fā)起 HTTP 請(qǐng)求將緩存過(guò)程分為兩個(gè)部分,分別是強(qiáng)制緩存協(xié)商緩存

強(qiáng)制緩存

強(qiáng)制緩存就是向?yàn)g覽器緩存查找該請(qǐng)求結(jié)果,并根據(jù)該結(jié)果的緩存規(guī)則來(lái)決定是否使用該緩存結(jié)果的過(guò)程,強(qiáng)制緩存的情況主要有三種:

  • 不存在該緩存結(jié)果和緩存標(biāo)識(shí),強(qiáng)制緩存失效,則直接向服務(wù)器發(fā)起請(qǐng)求(跟第一次發(fā)起請(qǐng)求一致),如下圖:
image
  • 存在該緩存結(jié)果和緩存標(biāo)識(shí),但該結(jié)果已失效,強(qiáng)制緩存失效,則使用協(xié)商緩存(暫不分析),如下圖:
image
  • 存在該緩存結(jié)果和緩存標(biāo)識(shí),且該結(jié)果尚未失效,強(qiáng)制緩存生效,直接返回該結(jié)果,如下圖:
image

那么強(qiáng)制緩存的緩存規(guī)則是什么?

Expires

Expires 是 HTTP/1.0 控制網(wǎng)頁(yè)緩存的字段,其值為服務(wù)器返回該請(qǐng)求結(jié)果緩存的到期時(shí)間,即再次發(fā)起該請(qǐng)求時(shí),如果客戶端的時(shí)間小于Expires 的值時(shí),直接使用緩存結(jié)果。

到了 HTTP/1.1,Expire 已經(jīng)被 Cache-Control 替代,原因在于 Expires 控制緩存的原理是使用客戶端的時(shí)間與服務(wù)端返回的時(shí)間做對(duì)比,那么如果客戶端與服務(wù)端的時(shí)間因?yàn)槟承┰颍ɡ鐣r(shí)區(qū)不同;客戶端和服務(wù)端有一方的時(shí)間不準(zhǔn)確)發(fā)生誤差,那么強(qiáng)制緩存則會(huì)直接失效,這樣的話強(qiáng)制緩存的存在則毫無(wú)意義,那么 Cache-Control 又是如何控制的呢?

Cache-Control

在 HTTP/1.1 中,Cache-Control 是最重要的規(guī)則,主要用于控制網(wǎng)頁(yè)緩存,主要取值為:

  • public:所有內(nèi)容都將被緩存(客戶端和代理服務(wù)器都可緩存)。

  • private:所有內(nèi)容只有客戶端可以緩存,Cache-Control 的默認(rèn)取值。

  • no-cache:客戶端緩存內(nèi)容,但是是否使用緩存則需要經(jīng)過(guò)協(xié)商緩存來(lái)驗(yàn)證決定。

  • no-store:所有內(nèi)容都不會(huì)被緩存,即不使用強(qiáng)制緩存,也不使用協(xié)商緩存。

  • max-age=xxx (xxx is numeric):緩存內(nèi)容將在 xxx 秒后失效。
    接下來(lái),我們直接看一個(gè)例子,如下:

image

由上面的例子我們可以知道:

HTTP 響應(yīng)報(bào)文中 expires 的時(shí)間值,是一個(gè)絕對(duì)值。

HTTP 響應(yīng)報(bào)文中 Cache-Control 為 max-age=600,是相對(duì)值。

由于 Cache-Control 的優(yōu)先級(jí)比 expires,那么直接根據(jù) Cache-Control 的值進(jìn)行緩存,意思就是說(shuō)在 600 秒內(nèi)再次發(fā)起該請(qǐng)求,則會(huì)直接使用緩存結(jié)果,強(qiáng)制緩存生效。

了解強(qiáng)制緩存的過(guò)程后,我們拓展性的思考一下:瀏覽器的緩存存放在哪里,如何在瀏覽器中判斷強(qiáng)制緩存是否生效?

image

這里我們以博客的請(qǐng)求為例,狀態(tài)碼為灰色的請(qǐng)求則代表使用了強(qiáng)制緩存,請(qǐng)求對(duì)應(yīng)的 Size 值則代表該緩存存放的位置,分別為 from memory cache 和 from disk cache。

那么 from memory cache 和 from disk cache 又分別代表的是什么呢?什么時(shí)候會(huì)使用 from disk cache,什么時(shí)候會(huì)使用from memory cache 呢?

from memory cache 代表使用內(nèi)存中的緩存,from disk cache 則代表使用的是硬盤(pán)中的緩存,瀏覽器讀取緩存的順序?yàn)?memory –> disk。

雖然我已經(jīng)直接把結(jié)論說(shuō)出來(lái)了,但是相信有不少人對(duì)此不能理解,那么接下來(lái)我們一起詳細(xì)分析一下緩存讀取問(wèn)題,這里仍讓以我的博客為例進(jìn)行分析:

  1. 訪問(wèn) https://heyingye.github.io/ –> 200

  2. 關(guān)閉博客的標(biāo)簽頁(yè) –> 重新打開(kāi) https://heyingye.github.io/ –> 200 (from disk cache)

  3. 刷新 –> 200(from memory cache)

看到這里可能有人小伙伴問(wèn)了,最后一個(gè)步驟刷新的時(shí)候,不是同時(shí)存在著 from disk cache 和 from memory cache 嗎?

對(duì)于這個(gè)問(wèn)題,我們需要了解內(nèi)存緩存(from memory cache)和硬盤(pán)緩存(from disk cache),如下:

  • 內(nèi)存緩存(from memory cache):內(nèi)存緩存具有兩個(gè)特點(diǎn),分別是快速讀取和時(shí)效性:

  • 快速讀?。簝?nèi)存緩存會(huì)將編譯解析后的文件,直接存入該進(jìn)程的內(nèi)存中,占據(jù)該進(jìn)程一定的內(nèi)存資源,以方便下次運(yùn)行使用時(shí)的快速讀取。

  • 時(shí)效性:一旦該進(jìn)程關(guān)閉,則該進(jìn)程的內(nèi)存則會(huì)清空。

  • 硬盤(pán)緩存(from disk cache):硬盤(pán)緩存則是直接將緩存寫(xiě)入硬盤(pán)文件中,讀取緩存需要對(duì)該緩存存放的硬盤(pán)文件進(jìn)行 I/O 操作,然后重新解析該緩存內(nèi)容,讀取復(fù)雜,速度比內(nèi)存緩存慢。

在瀏覽器中,瀏覽器會(huì)在 js 和圖片等文件解析執(zhí)行后直接存入內(nèi)存緩存中,那么當(dāng)刷新頁(yè)面時(shí)只需直接從內(nèi)存緩存中讀?。欢?css 文件則會(huì)存入硬盤(pán)文件中,所以每次渲染頁(yè)面都需要從硬盤(pán)讀取緩存。

協(xié)商緩存

協(xié)商緩存就是強(qiáng)制緩存失效后,瀏覽器攜帶緩存標(biāo)識(shí)向服務(wù)器發(fā)起請(qǐng)求,由服務(wù)器根據(jù)緩存標(biāo)識(shí)決定是否使用緩存的過(guò)程。

主要有以下兩種情況:

  • 協(xié)商緩存生效,返回 304,如下:

    image
  • 協(xié)商緩存失效,返回 200 和請(qǐng)求結(jié)果結(jié)果,如下:

    image

同樣,協(xié)商緩存的標(biāo)識(shí)也是在響應(yīng)報(bào)文的 HTTP 頭中和請(qǐng)求結(jié)果一起返回給瀏覽器的,控制協(xié)商緩存的字段分別有:

  • Last-Modified / If-Modified-Since.

  • Etag / If-None-Match.

其中 Etag / If-None-Match 的優(yōu)先級(jí)比 Last-Modified / If-Modified-Since 高。

Last-Modified / If-Modified-Since

  • Last-Modified 是服務(wù)器響應(yīng)請(qǐng)求時(shí),返回該資源文件在服務(wù)器最后被修改的時(shí)間,如下:
image
  • If-Modified-Since 則是客戶端再次發(fā)起該請(qǐng)求時(shí),攜帶上次請(qǐng)求返回的 Last-Modified 值,通過(guò)此字段值告訴服務(wù)器該資源上次請(qǐng)求返回的最后被修改時(shí)間。服務(wù)器收到該請(qǐng)求,發(fā)現(xiàn)請(qǐng)求頭含有 If-Modified-Since 字段,則會(huì)根據(jù) If-Modified-Since 的字段值與該資源在服務(wù)器的最后被修改時(shí)間做對(duì)比,若服務(wù)器的資源最后被修改時(shí)間大于 If-Modified-Since 的字段值,則重新返回資源,狀態(tài)碼為 200;否則則返回 304,代表資源無(wú)更新,可繼續(xù)使用緩存文件,如下:
image

Etag / If-None-Match

  • Etag 是服務(wù)器響應(yīng)請(qǐng)求時(shí),返回當(dāng)前資源文件的一個(gè)唯一標(biāo)識(shí)(由服務(wù)器生成),如下:
image
  • If-None-Match 是客戶端再次發(fā)起該請(qǐng)求時(shí),攜帶上次請(qǐng)求返回的唯一標(biāo)識(shí) Etag 值,通過(guò)此字段值告訴服務(wù)器該資源上次請(qǐng)求返回的唯一標(biāo)識(shí)值。服務(wù)器收到該請(qǐng)求后,發(fā)現(xiàn)該請(qǐng)求頭中含有 If-None-Match,則會(huì)根據(jù) If-None-Match 的字段值與該資源在服務(wù)器的 Etag值做對(duì)比,一致則返回 304,代表資源無(wú)更新,繼續(xù)使用緩存文件;不一致則重新返回資源文件,狀態(tài)碼為 200,如下:

    image

總結(jié)

強(qiáng)制緩存優(yōu)先于協(xié)商緩存進(jìn)行,若強(qiáng)制緩存 Expires 和 Cache-Control 生效則直接使用緩存,若不生效則進(jìn)行協(xié)商緩存(Last-Modified / If-Modified-Since 和 Etag / If-None-Match)。

協(xié)商緩存由服務(wù)器決定是否使用緩存,若協(xié)商緩存失效,那么代表該請(qǐng)求的緩存失效,重新獲取請(qǐng)求結(jié)果,再存入瀏覽器緩存中;生效則返回 304,繼續(xù)使用緩存,主要過(guò)程如下:

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概述 瀏覽器的緩存機(jī)制也就是我們說(shuō)的HTTP緩存機(jī)制,其機(jī)制是根據(jù)HTTP報(bào)文的緩存標(biāo)識(shí)進(jìn)行的,所以在分析瀏覽器緩...
    skogt閱讀 241評(píng)論 0 0
  • 一、前言 緩存可以說(shuō)是性能優(yōu)化中簡(jiǎn)單高效的一種優(yōu)化方式了。一個(gè)優(yōu)秀的緩存策略可以縮短網(wǎng)頁(yè)請(qǐng)求資源的距離,減少延遲,...
    浪里行舟閱讀 208,987評(píng)論 46 521
  • 來(lái)源: https://www.infoq.cn/article/8VU-VCrhoxducaFPrNOL 一、前...
    AAA前端閱讀 331評(píng)論 0 2
  • 什么是瀏覽器緩存: 簡(jiǎn)單來(lái)說(shuō):瀏覽器緩存就是把一個(gè)已經(jīng)請(qǐng)求過(guò)的web資源(如html頁(yè)面,圖片,js,數(shù)據(jù)等)拷貝...
    路上靈魂的自由者閱讀 711評(píng)論 0 0
  • 前幾日去拜訪一位老先生,雖只閑聊,于本人卻是震撼不少,思索許久,寫(xiě)文記之。 按圖索驥,穿過(guò)林蔭道就到了所知的樓下。...
    天價(jià)勞力女士閱讀 1,490評(píng)論 0 0

友情鏈接更多精彩內(nèi)容