完全理解瀏覽器緩存機制

 

 


先看上圖,若是對圖中的(a)(b)(c)(d)四個過程的處理方式都很清楚了,那麼請不用再看本文了。css

兩個概念

  • 強緩存
    用戶發送的請求,直接從客戶端緩存中獲取,不發送請求到服務器,不與服務器發生交互行爲。html

  • 協商緩存
    用戶發送的請求,發送到服務器後,由服務器斷定是否從緩存中獲取資源。chrome

  • 二者共同點:客戶端得到的數據最後都是從客戶端緩存中得到。瀏覽器

  • 二者的區別:從名字就能夠看出,強緩存不與服務器交互,而協商緩存則須要與服務器交互。緩存

四個過程詳解

(a)瀏覽器斷定是否有緩存

先理解個概念,所謂「客戶端緩存」就是指用戶設備中本地資源。不一樣瀏覽器緩存文件的地址也不盡相同。
咱們以chrome爲例來查看下瀏覽器緩存文件的地址,
1)首先在chrome中輸入:chrome://chrome-urls/,看到一堆列表,裏面隱藏了許多瀏覽器的奧祕,有興趣的能夠本身深扒
2)找到 chrome://cache(固然也能夠直接輸入這個地址
爲了驗證緩存,咱們打開百度,打開開發者模式,去掉disable-cache選項
服務器

從上圖中能夠看到,第一個從緩存中取的文件是: https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/css/super_min_fec0412a.css
而後回到chrome://cache 頁面,找到它,並點擊進去,能夠看到:

回到問題,瀏覽器怎麼斷定是否有緩存,就能夠轉化爲瀏覽器去讀取本地放緩存的地方(注:不一樣瀏覽器不一樣系統都會不一樣)是否有該對應的請求啦。markdown

總結來講就是個查找文件是否存在的問題。

(b)緩存是否過時


咱們再以這張圖爲例,這張圖中代表,客戶端保留了一個服務器端的response header。
裏面的Date字段代表這次緩存時服務器的時間。
裏面有兩個字段:expires 、Cache-Control負載均衡

  • expires
    Http1.0 中的標準,代表過時時間,注意此處的時間都是指的是服務器的時間。
    能夠看到過時時間被設定爲了:Thu, 28 Sep 2017 06:38:37 GMT分佈式

    存在的問題:服務器時間與客戶端時間的不一致,就會致使緩存跟期待效果出現誤差。

  • Cache-Control
    Http1.1 中的標準,能夠當作是 expires 的補充。使用的是相對時間的概念。
    簡單介紹下Cache-Control的屬性設置。
    1)max-age: 設置緩存的最大的有效時間,單位爲秒(s)。max-age會覆蓋掉Expires
    2) s-maxage: 只用於共享緩存,好比CDN緩存(s -> share)。與max-age 的區別是:max-age用於普通緩存,
    而s-maxage用於代理緩存。若是存在s-maxage,則會覆蓋max-age 和 Expires.
    3) public:響應會被緩存,而且在多用戶間共享。默認是public。
    4) private: 響應只做爲私有的緩存,不能在用戶間共享。若是要求HTTP認證,響應會自動設置爲private。
    5)no-cache: 指定不緩存響應,代表資源不進行緩存。可是設置了no-cache以後並不表明瀏覽器不緩存,而是在緩存前要向服務器確認資源是否被更改。所以有的時候只設置no-cache防止緩存仍是不夠保險,還能夠加上private指令,將過時時間設爲過去的時間。
    6)no-store: 絕對禁止緩存。
    7)must-revalidate: 若是頁面過時,則去服務器進行獲取。
    設置cache-control 的規則能夠參見下圖:
    post

因此判斷緩存是否過時步驟是:
1) 查看是否有cache-control 的max-age / s-maxage , 若是有,則用服務器時間date值 + max-age/s-maxage 的秒數計算出新的過時時間,將當前時間與過時時間進行比較,判斷是否過時
2)查看是否有cache-control 的max-age / s-maxage,則用expires 做爲過時時間比較

總結:(b)過程執行完後,若是斷定爲未過時,則使用客戶端緩存。那麼就是屬於「強緩存」。

(c)跟服務器協商是否使用緩存


到這一步的時候,瀏覽器會向服務器發送請求,同時若是上一次的緩存中有Last-modified 和 Etag 字段,
瀏覽器將在request header 中加入If-Modified-Since(對應於Last-modified), 和If-None-Match(對應於Etag)。

  • Last-modified: 代表請求的資源上次的修改時間。
  • If-Modified-Since:客戶端保留的資源上次的修改時間。
  • Etag:資源的內容標識。(不惟一,一般爲文件的md5或者一段hash值,只要保證寫入和驗證時的方法一致便可)
  • If-None-Match: 客戶端保留的資源內容標識。

    ⚠️:

    1) 分佈式系統儘可能關閉Etag,由於每臺機器生成的Etag都不同。
    2)分佈式系統裏多臺機器間文件的Last-Modified必須一致,以避免負載均衡不一樣致使對比失敗。

一般狀況下,若是同時發送 If-None-Match 、If-Modified-Since字段,服務器只要比較etag 的內容便可,固然具體處理方式,看服務器的約定規則。

(d)協商緩存

在這個階段,服務器通常會將Cache-control、expires 、last-modified、date、etag 等字段在response header 中返回,便於下次緩存。固然具體的場景,也是看服務器的約定規則設定。

緩存的不一樣來源

⚠️: 這個問題暫時沒有找到很是滿意的、清楚的回答。

from disk cache

從磁盤中獲取緩存資源,等待下次訪問時不須要從新下載資源,而直接從磁盤中獲取。它的直接操做對象爲CurlCacheManager。

from memory cache

從內存中獲取資源,等待下次訪問時不須要從新下載資源,而直接從內存中獲取。Webkit早已支持memoryCache。
目前Webkit資源分紅兩類,一類是主資源,好比HTML頁面,或者下載項,一類是派生資源,好比HTML頁面中內嵌的圖片或者腳本連接,分別對應代碼中兩個類:    MainResourceLoader和SubresourceLoader。雖然Webkit支持memoryCache,可是也只是針對派生資源,它對應的類爲CachedResource,用於保存原始數據(好比CSS,JS等),以及解碼過的圖片數據。

區別

當退出進程時,內存中的數據會被清空,而磁盤的數據不會,因此,當下次再進入該進程時,該進程仍能夠從diskCache中得到數據,而memoryCache則不行。

類似

diskCache與memoryCache類似之處就是也只能存儲一些派生類資源文件。它的存儲形式爲一個index.dat文件,記錄存儲數據的url,而後再分別存儲該url的response信息和content內容。Response信息最大做用就是用於判斷服務器上該url的content內容是否被修改。

用戶行爲

最後附上一張,用戶行爲影響瀏覽器的緩存行爲。

總結

自此能夠將本文開頭的流程圖理解清楚。

遺留問題

  • CDN緩存?
  • param: no-cache?
  • 分佈式系統 ?
  • 負載均衡?
  • 緩存資源的存儲與讀取,瀏覽器是以什麼規則去區分memory cache , 仍是disk cache ?

參考文獻

Chrome瀏覽器的緩存文件位置: http://jingyan.baidu.com/article/f3e34a128e41acf5ea653554.html
瀏覽器緩存機制:http://www.cnblogs.com/skynet/archive/2012/11/28/2792503.html
瀏覽器緩存知識小結及應用: http://mp.weixin.qq.com/s/HRrYWnZIWgE_Hawr81CZTw
200 ok 幾種狀態:http://www.cnblogs.com/tangyuu/p/6396644.html

相關文章
相關標籤/搜索