基於HTTP瀏覽器緩存機制全面解析

什麼是瀏覽器緩存

Web緩存是指一個Web資源(如html頁面,圖片,js,數據等)存在於Web服務器和客戶端(瀏覽器)之間的副本。緩存會根據進來的請求保存輸出內容的副本;當下一個請求來到的時候,如果是相同的URL,緩存會根據緩存機制決定是直接使用副本響應訪問請求,還是向源服務器再次發送請求。

比較常見的就是瀏覽器會緩存訪問過網站的網頁,當再次訪問這個URL地址的時候,如果網頁沒有更新,就不會再次下載網頁,而是直接使用本地緩存的網頁。

隻有當網站明確標識資源已經更新,瀏覽器才會再次下載網頁。瀏覽器和網站服務器是根據緩存機制進行緩存的

非HTTP協議定義的緩存機制

瀏覽器緩存機制,其實主要就是HTTP協議定義的緩存機制(如: Expires; Cache-control等)。但是也有非HTTP協議定義的緩存機制,如使用HTML Meta 標簽,Web開發者可以在HTML頁面的節點中加入標簽

<meta http-equiv="Pragma" content="no-cache">

上述代碼的作用是告訴瀏覽器當前頁面不被緩存,每次訪問都需要去服務器拉取。使用上很簡單,但隻有部分瀏覽器可以支持,而且所有緩存代理服務器都不支持,因為代理不解析HTML內容本身。

緩存流程圖

利用瀏覽器緩存的過程:

在這裡插入圖片描述

HTTP緩存機制

根據Response Header裡面的Cache-Control和Expires這兩個屬性,當兩個都存在時,Cache-Control優先級較高。

Cache-Control

在這裡插入圖片描述

該字段用於控制瀏覽器在什麼情況下直接使用本地緩存而不向服務器發送請求。一般具有以下值:

  • Public:指示響應可被任何緩存區緩存。
  • Private:指示對於單個用戶的整個或部分響應消息,不能被共享緩存處理。這允許服務器僅僅描述當用戶的部分響應消息,此響應消息對於其他用戶的請求無效。
  • no-cache:指示請求或響應消息不能緩存。
  • no-store:用於防止重要的信息被無意的發佈。在請求消息中發送將使得請求和響應消息都不使用緩存。
  • max-age:指示瀏覽器可以接收生存期不大於指定時間(以秒為單位)的響應。
  • min-fresh:指示瀏覽器可以接收響應時間小於當前時間加上指定時間的響應。
  • max-stale:指示瀏覽器可以接收超出超時期間的響應消息。如果指定max-stale消息的值,那麼瀏覽器可以接收超出超時期指定值之內的響應消息。

Expires(石器時代的緩存機制)

Expires 頭部字段提供一個日期和時間,在該日期前的所有對該資源的請求都會直接使用瀏覽器緩存而不用向服務器請求。

例如:Expires: Sun, 08 Nov 2009 03:37:26 GMT

註意:

  • cache-control max-age 和 max-stale將覆蓋Expires header。
  • 使用Expires存在服務器端時間和瀏覽器時間不一致的問題。
  • 另外有人說Expires 是HTTP 1.0的東西,現在默認瀏覽器均默認使用HTTP 1.1。

服務端如何判斷緩存已失效

服務端通過If-Modified-Since(Last-Modified)和If-None-Match(Etag)這兩個屬性的值來判斷緩存是否失效的。

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since要配合Cache-Control使用。

Last-Modified:響應資源的最後修改時間。

If-Modified-Since:當緩存過期時,發現資源具有Last-Modified聲明,則在請求頭帶上If-Modified-Since(值就是Last-Modified)。服務器收到請求後發現有頭If-Modified-Since則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應HTTP 200整片資源內容(寫在響應消息包體內);若最後修改時間較舊,說明資源無新修改,則響應HTTP 304,告知瀏覽器繼續使用所保存的cache。

Etag/If-None-Match

Etag/If-None-Match也要配合Cache-Control使用。

Etag:資源在服務器的唯一標識(生成規則由服務器決定)。Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後得到的。

If-None-Match:當緩存過期時,發現資源具有Etage聲明,則在請求頭帶上If-None-Match(值就是Etag)。服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304。

為什麼有瞭Last-Modified還要Etag?

Etag的出現主要是為瞭解決幾個Last-Modified比較難解決的問題:

  • Last-Modified標註的最後修改隻能精確到秒級,如果某些文件在1秒鐘以內,被修改多次的話,它將不能準確標註文件的修改時間。
  • 如果某些文件會被定期生成,當有時內容並沒有任何變化,但Last-Modified卻改變瞭,導致文件沒法使用緩存。
  • 有可能存在服務器沒有準確獲取文件修改時間,或者與代理服務器時間不一致等情形。

200 OK(from cache)與304 Not Modified的區別

200 OK( from cache )不向服務器發送請求,直接使用本地緩存文件。304 Not Modified則向服務器詢問,若服務器認為瀏覽器的緩存版本還可用,那麼便會返回304。

200 OK( from cache ) 出現操作:

1.地址欄回車

2.頁面鏈接跳轉

3.前進、後退

304 Not Modified 出現操作:

1.F5刷新

2.新開窗口

緩存的不同來源

from disk cache:從磁盤中獲取緩存資源,等待下次訪問時不需要重新下載資源,而直接從磁盤中獲取。它的直接操作對象為CurlCacheManager。

from memory cache:從內存中獲取資源,等待下次訪問時不需要重新下載資源,而直接從內存中獲取。

兩者區別:當退出進程時,內存中的數據會被清空,而磁盤的數據不會,所以,當下次再進入該進程時,該進程仍可以從diskCache中獲得數據,而memoryCache則不行。

不能被緩存的請求

當然並不是所有請求都能被緩存。

無法被瀏覽器緩存的請求:

  • HTTP信息頭中包含Cache-Control:no-cache,pragma:no-cache(HTTP1.0),或Cache-Control:max-age=0等告訴瀏覽器不用緩存的請求
  • 需要根據Cookie,認證信息等決定輸入內容的動態請求是不能被緩存的
  • 經過HTTPS安全加密的請求
  • POST請求無法被緩存
  • HTTP響應頭中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的請求無法被緩存

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: