一文讀懂HTTP緩存機制

http緩存機制

一句話概況:本地緩存請求到的資源,後續請求儘量直接複用這些資源,減小Http請求,從而顯著提升網站和應用程序的性能。web

那麼何時緩存資源到本地?緩存資源何時過時?什麼狀況下使用這些緩存的資源呢?本文就帶着這三個問題開始展開。算法

HTTP緩存機制流程

從流程中能夠看到,瀏覽器發起資源請求後,大體有三部分:強緩存校驗、協商緩存校驗、資源請求。本文主要講解強緩存和協商緩存模塊,資源請求部分就是正常的一次HTTP交互過程,但值得注意的是:

由於通常只有GET請求才會被緩存,因此這裏泛指通常的GET資源請求。瀏覽器

強緩存

不須要額外向服務端發送請求,直接使用本地緩存。在Chrome瀏覽器中本地強緩存分爲兩類,一類是disk cache,一類是memory cache,查看devtools中的Networks會看到請求狀態爲200,而且後面跟着from disk cachefrom memory cache的請求就是使用了強緩存,以下面兩個圖。緩存

本人也還沒有了解Chrome瀏覽器如何控制兩種強緩存,故不展開了,以避免誤導讀者,但願能有高手指出!!!!這裏放上找到的Chrome官方文檔中的描述,其大致意思是兩種強緩存策略與渲染進程的生命週期有關,渲染進程的週期又大體與tab選項卡相對應:服務器

Chrome employs two caches — an on-disk cache and a very fast in-memory cache. The lifetime of an in-memory cache is attached to the lifetime of a render process, which roughly corresponds to a tab. Requests that are answered from the in-memory cache are invisible to the web request API.性能

是否使用強緩存由HTTP的三個頭部字段來控制:ExpiresPragmaCache-Control網站

Expires

Exipres字段是Http/1.0中的字段,其優先級在三個緩存控制字段中最低。代理

如圖所示,響應頭中Expires的值是一個時間戳,發起請求時,若是本地系統時間在這個時間戳以前,則緩存有效,不然緩存失效,進入協商緩存。若該響應頭中Expires設置爲無效的日期,好比 0, 則表明着過去的日期,即該資源已通過期。code

Cache-Control

Cache-ControlHTTP/1.1 中規定的通用頭部字段,經常使用屬性以下:

  • no-store:禁止使用緩存,每次請求都去服務端拿最新的資源;
  • no-cache:不使用強緩存,直接進入協商緩存模塊,向服務端請求校驗資源是否「新鮮」;
  • private:私有緩存,中間代理服務端不可緩存資源
  • public:公共緩存,中間代理服務端能夠緩存資源
  • max-age:單位:秒,緩存的最長有效時間。其起始時間爲緩存時響應頭中的Date字段,即有效期到responseDate + max-age,發起請求時超過該時間則緩存過時。
  • must-revalidate:緩存一旦過時,則必須從新向服務端驗證。

Pragma

PragmaHTTP/1.0 中規定的通用頭部字段,用於向後兼容只支持 HTTP/1.0 協議的緩存服務端。這個字段只有一個值:no-cache,其表現行爲與Cache-Control: no-cache一致,可是HTTP的響應頭沒有明肯定義這個屬性,因此它不能拿來徹底替代HTTP/1.1中定義的Cache-control頭。cdn

若是PragmaCache-Control 兩個字段同時存在,Pragma的優先級大於Cache-Control

協商緩存

當強緩存過時或者請求頭字段設置不走強緩存,好比Cache-Control:no-cachePragma:no-cache,則進入協商緩存部分。協商緩存涉及兩對頭部字段,分別是Last-Modified/If-Modified-Since、和ETag/If-None-Match

若請求頭中攜帶If-Modified-SinceIf-None-Match字段,則會發起去服務端校驗資源是否有變化,若是有變化,則未命中緩存,服務端返回200,瀏覽器計算響應體資源是否緩存並使用資源;若是未變換,則命中緩存,返回304,瀏覽器根據響應頭更新緩存頭部信息,延長有效期,並直接使用緩存。

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since的值是資源修改時間。第一次請求資源時,服務端將資源的最後修改時間放到響應頭的 Last-Modified 字段中,第二次請求該資源時,瀏覽器會自動將該資源上一次響應頭中的Last-Modified的值放到第二次請求頭的If-Modified-Since字段中,服務端比較服務端資源的最後一次修改時間和請求頭中的If-Modified-Since 的值,若是相等,則命中緩存返回 304,不然,返回200。

ETag/If-None-Match

ETag/If-None-Match 的值是一串hash值(hash算法不統一),是資源的標識符,當資源內容發生變化,其hash值也會改變。其過程與上面的類似,不過服務端是比較服務端資源的hash值和請求頭中的If-None-Match的值,但比較方式有所區別,由於ETag有兩種類型:

  • 強校驗:資源hash值具備惟一性,一旦變化則hash也變化。
  • 弱校驗:資源hash值以W/開頭,若資源變化較小,則一樣可能命中緩存。

例以下面這樣:

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4" ETag: W/"0815"

二者區別

  1. ETag/If-None-Match優先級比Last-Modified/If-Modified-Since高;
  2. Last-Modified/If-Modified-Since有個1S問題,即服務端在1S內修改文件,且再次受到請求時,會錯誤的返回304

代理服務緩存

VaryHTTP/1.1中的一個頭字字段,其值爲請求頭中的字段,如上圖中的 Accept-Encoding,能夠是多個,以逗號分割,其記錄了代理服務器返回資源參考了哪些請求頭字段。代理服務器拿到源服務器的響應報文,會根據 Vary 裏的字段列表,緩存不一樣版本的資源。當有資源請求再次訪問時,代理服務器會分析請求頭字段,返回正確的版本。

總結

在實際應用過程,對一些更新不頻繁的資源合理使用緩存機制,能夠有效提升系統的響應速度,提升用戶體驗。

相關文章
相關標籤/搜索