淺析HTTP緩存

前言

沒有緩存的瀏覽器是無源之水、無根之木,需要通過不等次數的網絡來回獲取資源,而網絡情況是不確定的,所以網絡請求一直被我們視爲洪水猛獸。

所以不管是爲了加快用戶訪問速度、改善用戶體驗,還是節約流量,存儲之前獲取的資源並留待以後重複利用勢在必行。

HTTP緩存主要是根據HTTP協議的約定,主要還是服務端通過HTTP頭部字段等進行控制,客戶端接收到相關字段並進行相應緩存存儲以及命中邏輯。

所以到底有哪些重要字段呢?

1. Cache-Control

  1. max-age
    設置緩存最大有效期,單位爲s,定義的是時間長短,需要配合時間字段使用,如Date。在max-age設定的有效期內,瀏覽器發出的請求會直接命中HTTP緩存,不會進入網絡堆棧。
  2. s-maxage
    用法同max-age,不過該字段只用於共享緩存(比如CDN緩存),當處理代理緩存時,如果存在s-maxage,那麼其會覆蓋掉max-age和expires。同理如果在s-maxage有效期內,即使CDN資源發生了改變,瀏覽器請求也不會進入網絡堆棧。
  3. no-cache
    不緩存響應,表示必須先和服務器確認返回的響應是否發生了變化,然後才能使用該響應來滿足後續請求命中緩存。場景一般是資源變化比較迅速,所以強制啓用ETag進行資源驗證,如果ETag等驗證通過,則可以返回304
  4. no-store
    絕對禁止瀏覽器以及中間緩存存儲任何版本的響應,場景一般是個人隱私數據或者安全性比較高的銀行數據等,強制要求每次請求資源必須進行用戶驗證和網絡來回。
  5. public
    相對於private是默認值,即使存在HTTP用戶認證等限制,緩存也會被響應,並且允許多用戶共享,比如CDN。
  6. private
    只作爲私有的緩存,不能再用戶間共享,不允許任何中間緩存對其進行緩存,比如CDN。如果要求HTTP認證,響應會自動設置爲private。

HTTP Cache-Control屬性決定樹

2. Expires

緩存過期時間,是具體的時間點,即絕對時間,數值上等於max-age + new Date().getTime() 。其優先級相對Cache-Control略低,主要用作兼容舊瀏覽器,具體作用與Cache-Control的max-age類似。

3. Last-Modified

語義爲資源最後修改時間,經常配合Cache-Control使用,是檢查資源更新的重要字段。當瀏覽器請求資源並且緩存已經不再有效期內或者no-cache,那麼我們需要進行網絡來回確認資源是否修改,此時瀏覽器根據Last-Modified會生成if-Modify-Since,服務端接收比對後如果沒有修改則返回304,直接使用緩存,如果修改了,則請求服務器最新資源。

4. ETag

服務端根據一定規則生成的hash字符串、UUID或類似物,用來進行資源狀態唯一標識,其作用過程如下:

ETag過程

其實作用與Last-Modified有重疊,我們只需比對修改時間是否一致即可,爲何還要比對ETag字符串呢?

因爲Last-Modified存在如下問題:

  1. 某些服務器不能精確得到資源的最後修改時間
  2. 如果資源修改非常平凡,在秒級別之下的時間內進行修改,而Last-Modified只能精確到秒
  3. 當資源最後時間修改過了,但內容沒變時,ETag不會變化,可以有效區分這種情況

大概就講這四個關鍵的header,如果想了解其他的header,可以看我另一篇博客HTTP協議知多少

總結

所以綜上所述,HTTP緩存的流程爲:

HTTP緩存響應流程

在制定緩存策略時,您需要牢記下面這些技巧和方法:(來自谷歌開發者《HTTP緩存》)

  • 使用一致的網址:如果您在不同的網址上提供相同的內容,將會多次獲取和存儲這些內容。提示:請注意,網址區分大小寫。
  • 確保服務器提供驗證令牌 (ETag):有了驗證令牌,當服務器上的資源未發生變化時,就不需要傳送相同的字節。
  • 確定中間緩存可以緩存哪些資源:對所有用戶的響應完全相同的資源非常適合由 CDN 以及其他中間緩存進行緩存。
  • 爲每個資源確定最佳緩存週期:不同的資源可能有不同的更新要求。爲每個資源審覈並確定合適的 max-age。
  • 確定最適合您的網站的緩存層次結構:您可以通過爲 HTML 文檔組合使用包含內容指紋的資源網址和短時間或 no-cache 週期,來控制客戶端獲取更新的速度。
  • 最大限度減少攪動:某些資源的更新比其他資源頻繁。如果資源的特定部分(例如 JavaScript 函數或 CSS 樣式集)會經常更新,可以考慮將其代碼作爲單獨的文件提供。這樣一來,每次獲取更新時,其餘內容(例如變化不是很頻繁的內容庫代碼)可以從緩存獲取,從而最大限度減少下載的內容大小。

參考

  1. 淺談 Web 緩存
  2. 淺談瀏覽器http的緩存機制
  3. HTTP緩存控制小結
  4. RFC文檔
  5. 谷歌開發者HTTP緩存
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章