HTTP協議 (四) 緩存

原文地址:http://www.cnblogs.com/TankXiao/archive/2012/11/28/2793365.html

之前寫過一個篇 【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

Fiddler中把header都分門別類的放在一起,這樣方便查看。

 

如何判斷緩存新鮮度

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給瀏覽器客戶端, 告訴客戶端直接使用緩存裏的版本。如下圖。

3. 假如該文檔已經被更新了。Web服務器將發送該文檔的最新版本給瀏覽器客戶端, 如下圖。

 

實例: 打開Fiddler, 然後打開博客園首頁。然後F5刷新幾次瀏覽器。 你會看到博客園首頁也用了緩存。

 

與緩存有關的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

ETag是實體標籤(Entity Tag)的縮寫, 根據實體內容生成的一段hash字符串(類似於MD5或者SHA1之後的結果),可以標識資源的狀態。 當資源發送改變時,ETag也隨之發生變化。

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

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

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

2. 某些文件的修改非常頻繁,在秒以下的時間內進行修改. Last-Modified只能精確到秒。

3. 一些文件的最後修改時間改變了,但是內容並未改變。 我們不希望客戶端認爲這個文件修改了。

 

實例, 打開Fiddler, 打開博客園首頁。  你可以看到很多圖片,或者CSS文件都是用了緩存。 這些都是通過比較ETag的值,來判斷文件是否更新了。

 

瀏覽器不使用緩存

CTRL+F5強制刷新瀏覽器,或者設置IE。  可以讓瀏覽器不使用緩存。

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

2. Web服務器將把最新的文檔發送給瀏覽器客戶端.

 

實例:

打開Fiddler, 打開博客園首頁, 然後按CTRL+F5強制刷新瀏覽器,你將看到

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 去服務器驗證緩存,這種情況叫做緩存命中,如下圖

 

實例: 比較第一次訪問博客園主頁和第二次博客園主頁

1. 啓動Fiddler, 用firefox打開博客園主頁, 發現有50多個session。

2. 按CTRL+X將Fiddler中的所有session刪除。 關閉firefox,重新打開一個firefox,打開博客園主頁。   發現只有30多個session.

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

 

 

如何設置IE不使用緩存

打開IE。點擊工具欄上的, 工具->Internet選項->常規->瀏覽歷史記錄 設置. 選擇“從不”。然後保存。

然後點擊“刪除”  把Internet臨時文件都刪掉 (IE緩存的文件就是Internet臨時文件)。

 

公有緩存和私有緩存的區別

Cache-Control: public 指可以公有緩存, 可以是數千名用戶共享的。

Cache-Control: private 指只支持私有緩存, 私有緩存是單個用戶專用的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章