天天看點

HTTP協定之緩存

HTTP協定之緩存

之前寫過一個篇 【HTTP協定詳解】 ,這次繼續介紹HTTP協定中的緩存機制。HTTP協定提供了非常強大的緩存機制, 了解這些緩存機制,對提高網站的性能非常有幫助。 本文介紹浏覽器和Web伺服器之間如何處理"浏覽器緩存",以及控制緩存的http header.

本文會使用Fiddler來檢視HTTP request和Response, 如果不熟悉這工具,可以先參考[Fiddler教程] 。在看本文的時候, 請務必打開Fiddler來實踐。

閱讀目錄

  1. 緩存的概念
  2. 緩存的好處
  3. Fiddler可以友善地檢視緩存的header
  4. 如何判斷緩存新鮮度
  5. 通過最後修改時間,判斷緩存新鮮度
  6. 與緩存相關的header
  7. ETag
  8. 浏覽器不使用緩存
  9. 直接使用緩存,不去伺服器端驗證
  10. 如何設定IE不使用緩存
  11. 公有緩存和私有緩存的差別

緩存這個東西真的是無處不在, 有浏覽器端的緩存, 有伺服器端的緩存,有代理伺服器的緩存, 有ASP.NET頁面緩存,對象緩存。 資料庫也有緩存, 等等。

http中具有緩存功能的是浏覽器緩存,以及緩存代理伺服器。

http緩存的是指:當Web請求抵達緩存時, 如果本地有“已緩存的”副本,就可以從本地儲存設備而不是從原始伺服器中提取這個文檔。

緩存的好處是顯而易見的, 好處有,

1. 減少了備援的資料傳輸,節省了網費。

2. 減少了伺服器的負擔, 大大提高了網站的性能

3. 加快了用戶端加載網頁的速度

Fiddler中把header都分門别類的放在一起,這樣友善檢視。

HTTP協定之緩存

Web伺服器通過2種方式來判斷浏覽器緩存是否是最新的。

第一種, 浏覽器把緩存檔案的最後修改時間通過 header ”If-Modified-Since“來告訴Web伺服器。

第二種, 浏覽器把緩存檔案的ETag, 通過header "If-None-Match", 來告訴Web伺服器。

通過最後修改時間, 來判斷緩存新鮮度

1. 浏覽器用戶端想請求一個文檔,  首先檢查本地緩存,發現存在這個文檔的緩存,  擷取緩存中文檔的最後修改時間,通過: If-Modified-Since, 發送Request給Web伺服器。

2. Web伺服器收到Request,将伺服器的文檔修改時間(Last-Modified): 跟request header 中的,If-Modified-Since相比較, 如果時間是一樣的, 說明緩存還是最新的, Web伺服器将發送304 Not Modified給浏覽器用戶端, 告訴用戶端直接使用緩存裡的版本。如下圖。

HTTP協定之緩存

3. 假如該文檔已經被更新了。Web伺服器将發送該文檔的最新版本給浏覽器用戶端, 如下圖。

HTTP協定之緩存

執行個體: 打開Fiddler, 然後打開部落格園首頁。然後F5重新整理幾次浏覽器。 你會看到部落格園首頁也用了緩存。

HTTP協定之緩存

與緩存有關的header

我們來看看每個header的具體含義。

Request

Cache-Control: max-age=0 以秒為機關
If-Modified-Since: Mon, 19 Nov 2012 08:38:01 GMT 緩存檔案的最後修改時間。
If-None-Match: "0693f67a67cc1:0" 緩存檔案的Etag值
Cache-Control: no-cache 不使用緩存
Pragma: no-cache

Response

Cache-Control: public 響應被緩存,并且在多使用者間共享,  (公有緩存和私有緩存的差別,請看另一節)
Cache-Control: private 響應隻能作為私有緩存,不能在使用者之間共享
Cache-Control:no-cache 提醒浏覽器要從伺服器提取文檔進行驗證
Cache-Control:no-store 絕對禁止緩存(用于機密,敏感檔案)
Cache-Control: max-age=60 60秒之後緩存過期(相對時間)
Date: Mon, 19 Nov 2012 08:39:00 GMT 目前response發送的時間
Expires: Mon, 19 Nov 2012 08:40:01 GMT 緩存過期的時間(絕對時間)
Last-Modified: Mon, 19 Nov 2012 08:38:01 GMT 伺服器端檔案的最後修改時間
ETag: "20b1add7ec1cd1:0" 伺服器端檔案的Etag值

如果同時存在cache-control和Expires怎麼辦呢?

浏覽器總是優先使用cache-control,如果沒有cache-control才考慮Expires  

ETag是實體标簽(Entity Tag)的縮寫, 根據實體内容生成的一段hash字元串(類似于MD5或者SHA1之後的結果),可以辨別資源的狀态。 當資源發送改變時,ETag也随之發生變化。

ETag是Web服務端産生的,然後發給浏覽器用戶端。浏覽器用戶端是不用關心Etag是如何産生的。

為什麼使用ETag呢? 主要是為了解決Last-Modified 無法解決的一些問題。

1. 某些伺服器不能精确得到檔案的最後修改時間, 這樣就無法通過最後修改時間來判斷檔案是否更新了。

2. 某些檔案的修改非常頻繁,在秒以下的時間内進行修改. Last-Modified隻能精确到秒。

3. 一些檔案的最後修改時間改變了,但是内容并未改變。 我們不希望用戶端認為這個檔案修改了。

執行個體, 打開Fiddler, 打開部落格園首頁。  你可以看到很多圖檔,或者CSS檔案都是用了緩存。 這些都是通過比較ETag的值,來判斷檔案是否更新了。

HTTP協定之緩存

CTRL+F5強制重新整理浏覽器,或者設定IE。  可以讓浏覽器不使用緩存。

1. 浏覽器發送Http request, 給Web 伺服器, header中帶有Cache-Control: no-cache.   明确告訴Web伺服器,用戶端不使用緩存。 

2. Web伺服器将把最新的文檔發送給浏覽器用戶端.

執行個體:

打開Fiddler, 打開部落格園首頁, 然後按CTRL+F5強制重新整理浏覽器,你将看到

HTTP協定之緩存

Pragma: no-cache的作用和Cache-Control: no-cache一模一樣。 都是不使用緩存。 

Pragma: no-cache 是HTTP 1.0中定義的, 是以為了相容HTTP 1.0. 是以會同時使用Pragma: no-cache和Cache-Control: no-cache

直接使用緩存,不去伺服器驗證

按F5重新整理浏覽器和在位址欄裡輸入網址然後回車。 這兩個行為是不一樣的。

按F5重新整理浏覽器, 浏覽器會去Web伺服器驗證緩存。

如果是在位址欄輸入網址然後回車,浏覽器會"直接使用有效的緩存", 而不會發http request 去伺服器驗證緩存,這種情況叫做緩存命中,如下圖

HTTP協定之緩存

執行個體: 比較第一次通路部落格園首頁和第二次部落格園首頁

1. 啟動Fiddler, 用firefox打開部落格園首頁, 發現有50多個session。

2. 按CTRL+X将Fiddler中的所有session删除。 關閉firefox,重新打開一個firefox,打開部落格園首頁。   發現隻有30多個session.

分析;  少了的session是因為firefox直接用了緩存,而沒有發http request。

HTTP協定之緩存

打開IE。點選工具欄上的, 工具->Internet選項->正常->浏覽曆史記錄 設定. 選擇“從不”。然後儲存。

然後點選“删除”  把Internet臨時檔案都删掉 (IE緩存的檔案就是Internet臨時檔案)。

HTTP協定之緩存

繼續閱讀