一張圖理解Http緩存

參閱了一些瀏覽器緩存的資料,本文經過一張圖來概括總結其過程。html

瀏覽器第一次向一個web服務器發起http請求後,服務器會返回請求的資源,而且在響應頭中添加一些有關緩存的字段如:Cache-ControlExpiresLast-ModifiedETagDate等等。以後瀏覽器再向該服務器請求該資源就能夠視狀況使用強緩存協商緩存web

  • 強緩存:瀏覽器直接從本地緩存中獲取數據,不與服務器進行交互。
  • 協商緩存:瀏覽器發送請求到服務器,服務器斷定是否可以使用本地緩存。
  • 聯繫與區別:兩種緩存方式最終使用的都是本地緩存;前者無需與服務器交互,後者須要。

下面假定瀏覽器已經訪問了服務器,服務器返回了緩存相關的頭部字段且瀏覽器已對相關資源作好緩存。經過下圖來分析強緩存和協商緩存:瀏覽器

clipboard.png

強緩存

如圖紅線所示的過程表明強緩存。用戶發起了一個http請求後,瀏覽器發現先本地已有所請求資源的緩存,便開始檢查緩存是否過時。有兩個http頭部字段控制緩存的有效期:ExpiresCache-Control,瀏覽器是根據如下兩步來斷定緩存是否過時的:緩存

  1. 查看緩存是否有Cache-Controls-maxagemax-age指令,如有,則使用響應報文生成時間Date + s-maxage/max-age得到過時時間,再與當前時間進行對比(s-maxage適用於多用戶使用的公共緩存服務器);
  2. 若是沒有Cache-Controls-maxagemax-age指令,則比較Expires中的過時時間與當前時間。Expires是一個絕對時間。

注意,在HTTP/1.1中,當首部字段Cache-Control有指定s-maxagemax-age指令,比起首部字段Expires,會優先處理s-maxagemax-age服務器

另外下面列幾個Cache-Control的經常使用指令:spa

  • no-cache:含義是不使用本地緩存,須要使用協商緩存,也就是先與服務器確認緩存是否可用。
  • no-store:禁用緩存。
  • public:代表其餘用戶也可以使用緩存,適用於公共緩存服務器的狀況。
  • private:代表只有特定用戶才能使用緩存,適用於公共緩存服務器的狀況。

通過上述兩步判斷後,若緩存未過時,返回狀態碼爲200,則直接從本地讀取緩存,這就完成了整個強緩存過程;若是緩存過時,則進入協商緩存或服務器返回新資源過程。code

協商緩存

當瀏覽器發現緩存過時後,緩存並不必定不能使用了,由於服務器端的資源可能仍然沒有改變,因此須要與服務器協商,讓服務器判斷本地緩存是否還能使用。此時瀏覽器會判斷緩存中是否有ETagLast-Modified字段,若是沒有,則發起一個http請求,服務器根據請求返回資源;若是有這兩個字段,則在請求頭中添加If-None-Match字段(有ETag字段的話添加)、If-Modified-Since字段(有Last-Modified字段的話添加)。注意:若是同時發送If-None-MatchIf-Modified-Since字段,服務器只要比較If-None-MatchETag的內容是否一致便可;若是內容一致,服務器認爲緩存仍然可用,則返回狀態碼304,瀏覽器直接讀取本地緩存,這就完成了協商緩存的過程,也就是圖中的藍線;若是內容不一致,則視狀況返回其餘狀態碼,並返回所請求資源。下面詳細解釋下這個過程:htm

1.ETagIf-None-Match

兩者的值都是服務器爲每份資源分配的惟一標識字符串。blog

  • 瀏覽器請求資源,服務器會在響應報文頭中加入ETag字段。資源更新時,服務器端的ETag值也隨之更新;
  • 瀏覽器再次請求資源時,會在請求報文頭中添加If-None-Match字段,它的值就是上次響應報文中的ETag的值;
  • 服務器會比對ETagIf-None-Match的值是否一致,若是不一致,服務器則接受請求,返回更新後的資源;若是一致,代表資源未更新,則返回狀態碼爲304的響應,可繼續使用本地緩存,要注意的是,此時響應頭會加上ETag字段,即便它沒有變化。

2.Last-ModifiedIf-Modified-Since

兩者的值都是GMT格式的時間字符串。ip

  • 瀏覽器第一次向服務器請求資源後,服務器會在響應頭中加上Last-Modified字段,代表該資源最後一次的修改時間;
  • 瀏覽器再次請求該資源時,會在請求報文頭中添加If-Modified-Since字段,它的值就是上次服務器響應報文中的Last-Modified的值;
  • 服務器會比對Last-ModifiedIf-Modified-Since的值是否一致,若是不一致,服務器則接受請求,返回更新後的資源;若是一致,代表資源未更新,則返回狀態碼爲304的響應,可繼續使用本地緩存,與ETag不一樣的是:此時響應頭中不會再添加Last-Modified字段。

3.ETag較之Last-Modified的優點

如下內容引用於:http協商緩存VS強緩存

你可能會以爲使用Last-Modified已經足以讓瀏覽器知道本地的緩存副本是否足夠新,爲何還須要ETag呢?HTTP1.1ETag的出現主要是爲了解決幾個Last-Modified比較難解決的問題:

  • 一些文件也許會週期性的更改,可是他的內容並不改變(僅僅改變的修改時間),這個時候咱們並不但願客戶端認爲這個文件被修改了,而從新GET
  • 某些文件修改很是頻繁,好比在秒如下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改沒法判斷(或者說UNIX記錄MTIME只能精確到秒);
  • 某些服務器不能精確的獲得文件的最後修改時間。

這時,利用ETag可以更加準確的控制緩存,由於ETag是服務器自動生成的資源在服務器端的惟一標識符,資源每次變更,都會生成新的ETag值。Last-ModifiedETag是能夠一塊兒使用的,但服務器會優先驗證ETag

用戶行爲

最後附一張圖說明用戶行爲對瀏覽器緩存的影響:
clipboard.png

相關文章
相關標籤/搜索