隨着用戶訪問量越來越大,緩存變得越來越重要。HTTP文件緩存可以減少冗餘數據的傳輸;緩解網絡瓶頸;降低對原始服務器的請求;以及降低距離延遲。
命中和未命中
有了緩存,就可以保留第一條服務器響應的副本,後繼請求就可以有緩存的副本來應對了。可以用已有的副本爲某些達到緩存的請求提供服務,這些被稱爲緩存命中(cache hit)。HTTP沒有爲用戶提供一種手段來區分響應是否緩存命中的,還是訪問原始服務器得到的。在客戶端使用Date首部,將響應中Date首部的值與當前時間進行比較,如果響應中的日期值比較早,客戶端通常就可以認爲是一條緩存的響應。現代瀏覽器通常會使用200 OK (from disk cache)進行標識來自緩存
再驗證
原始服務器的內容可能會發生變化,緩存要不時的對其進行檢測,看看它們保存的副本是否仍是服務器上最新的副本,這些“新鮮度檢測”被稱爲HTTP再驗證(revalidation)。
文檔過期
通過特殊的HTTP Cache-Control:max-age
首部(HTTP/1.1)和Expires
首部(HTTP/1.0+),HTTP讓原始服務器向每個文檔附件一個“過期日期”。在文檔過期之前,緩存可以以任意頻率使用這些副本,而無需與服務器聯繫(不會發起任何請求)。
首部 | 描述 |
---|---|
Cache-Control:max-age |
max-age值定義了文檔的最大使用期—從第一次生成文檔到文檔不再新鮮、無法使用爲止(單位:秒) Cache-Control:max-age=3600 |
Expires |
指定一個絕對的過期日期 Expires:Fri, 30 Jun 2017 11:40:21 GMT |
用條件方法進行再驗證
HTTP的條件方法可以高效地實現再驗證。HTTP允許緩存向原始服務器發送一個“條件Get請求”,請求服務器只有在文檔與緩存中現有的副本不同時,纔回送對象主體;否則值返回304 Not Modified,不攜帶主體。
首部 | 描述 |
---|---|
If-Modified-Since:<date> |
如果從指定日期之後文檔被修改過了,就執行請求的方法。可以與Last-Modified 服務器響應首部配合使用,只有在內容被修改後與已緩存版本有所不同時纔去獲取內容。 |
If-None-match:<tags> |
服務器可以爲文檔提供特殊的標籤ETag,而不是將其與最近日期相匹配,這些標籤就像序列號一樣。如果已緩存標籤與服務器文檔中的標籤有所不同,就會執行請求的方法。 |
如果服務器發送了一個實體標籤,HTTP/1.1客戶端就必須使用實體標籤驗證器。如果服務器只回送了一個Last-Modified值,客戶端就可以使用If-Modified-Since驗證。如果都提供了,HTTP/1.0和HTTP/1.1緩存都可以正確響應。
緩存的處理步驟
(1)接收—緩存從網絡中讀取抵達的請求報文;
(2)解析—緩存對報文進行解析,提取出URL和各種首部;
(3)查詢—緩存查看是否已有本地副本可用,如果沒有,就獲取一份副本(並將其保存在本地);
(4)新鮮度檢測—緩存查看已緩存副本是否足夠新鮮,如果不是,就詢問服務器是否有任何更新條件Get請求;
(5)創建響應—緩存會用新的首部和已緩存的主體來構建一條響應報文;
(6)發送—緩存通過網絡將響應發回給客戶端;
(7)日誌—緩存可選地創建一個日誌文件條目來描述這個事物。
Cache-Control:相對時間(秒爲單位)
(或者,Expires:絕對時間
)如果未過期,直接讀取瀏覽器緩存文件,不發生任何HTTP請求。- 在瀏覽器端判斷上次返回頭中是否包含Etag信息,有則連同If-None-Match一起向服務器端發送條件Get請求,304說明未做過修改,如果是200需要進入下一步;
- 在瀏覽器端判斷上次返回頭中是否包含Last-Modify信息,有則連同If-Modified-Since一起向服務器端發送條件Get請求,內容失效返回200,否則304;
- 如果Etag和Last-Modify都不存在,直接向服務器請求。
**注意:**如果返回304,不會有內容,節省請求大小!
控制緩存的能力
服務器可以通過HTTP定義的幾種方式來指定在文檔過期之前可以將其緩存多長時間。按照優先級遞減的順序:
- 附件一個
Cache-Control: no-store
首部到響應中去; - 附件一個
Cache-Control: no-cache
首部到響應中去; - 附件一個
Cache-Control: must-revalidate
首部到響應中去; - 附件一個
Cache-Control: max-age
首部到響應中去; - 附加一個
Expires
日期首部到響應中去; - 不附加過期信息,讓緩存確定自己的過期日期。
**注意:**標識爲no-store
的響應會禁止緩存對響應進行復制。緩存通常會像非緩存代理服務器一樣,向客戶端轉發一條no-store
響應,熱後刪除對象;標識爲no-cache
的響應實際上是可以存儲在本地緩存區中的,只是在與原始服務器進行新鮮度再驗證之前,緩存不能將其提供給客戶端使用。
客戶端的新鮮度限制
Web瀏覽器都有Refresh(刷新)或Reload(重載)按鈕,可以強制對瀏覽器或代理緩存中可能過期的內容進行刷新。Refresh按鈕會發佈一個附加了Cache-Control
請求首部的Get請求,這個請求會強制進行再驗證,或者無條件地從服務器獲取文檔。
Safari/Firefox瀏覽器下通過Cache-Control:max-age=0
進行控制;Chrome瀏覽器勾選Disable cache下通過Cache-Control:no-cache Pragma:no-cache
注意:HTML2.0定義了<META HTTP-EQUIV="Cache-control" CONTENT="no-cache">
來標記非緩存,其並不是控制文檔緩存特性的最好方法。
緩存和廣告
廣告通常是向用戶顯示一次廣告內容,內容提供商就會得到相應的收益。緩存—它們會向原始服務器隱藏實際的訪問次數。現在廣告商會使用各種類型的“緩存清除”技術來確保緩存不會竊取他們的命中流量。**常用解決方案:**每次訪問都與原始服務器進行再驗證(攜帶no-cache或每次訪問重寫廣告URL)。這樣,每次訪問都會將命中推向原始服務器,但通常不會傳送任何主題數據,不會降低失誤處理速度。
緩存層次結構
其基本思想是在靠近客戶端的地方使用小型廉價緩存,而更高層次中,則逐步採用更大、功能更強的緩存來裝載多用戶共享的文檔。