瀏覽器與服務端協商緩存

##協商過程 協商的過程很容易理解,首先,當瀏覽器向Web服務器請求一些內容時,Web服務器須要告訴瀏覽器哪些內容能夠被緩存,一旦瀏覽器知道某個內容能夠緩存後,下次當瀏覽器須要請求這個內容時,它便不會直接向服務器請求完整內容,而是詢問服務器是否可使用本地的緩存,服務器在收到瀏覽器的詢問後須要做出果斷的迴應,究竟是容許瀏覽器使用本地緩存仍是將最新的內容傳回瀏覽器。算法

##Last-Modified(If-Modified-Since/304) HTTP協議中規定使用GMT時間,也就是格林威治標準時間,而咱們國家使用的是GMT+8時區,因此在HTTP頭信息中的時間會比咱們的正常時間早8個小時,但它一點都不影響HTTP緩存的正常工做。瀏覽器

HTTP響應頭中多出瞭如下的標記: Last-Modified: Fri, 20 Mar 2009 07:53:02 GMT 瀏覽器再也不無動於衷,它在HTTP請求頭中增長了如下這段標記: If-Modified-Since: Fri, 20 Mar 2009 07:53:02 GMT緩存

這意味着瀏覽器在詢問Web服務器:「我請求的內容在這個時間以後是否有更新?」此時Web服務器肩負起了重要責任,它須要檢查這個內容在該時間後是否有過更新,並反饋給瀏覽器,這一過程便至關於咱們傳統意義上的緩存過時檢查,對於靜態內容來講,Web服務器能夠輕鬆搞定,只要得到靜態文件的最後修改時間並將其和瀏覽器詢問的時間進行對比便可。服務器

這裏咱們須要關注的是響應狀態碼的變化,304 Not Modified意味着Web服務器告訴瀏覽器,這個內容沒有更新,瀏覽器可使用本地緩存的內容。同時,Web服務器沒有將內容的正文傳送給瀏覽器。 ##Etag(If-None-Match/304) HTTP/1.1還支持另外一種緩存協商方法,那就是ETag,它與前面所講的協商方式很是相似,但它沒有采用內容的最後修改時間,而是採用了一串編碼來標記內容,稱爲ETag。一個原則是,若是一個內容的ETag沒有變化,那麼這個內容也必定沒有更新。負載均衡

ETag由Web服務器來生成,好比Apache爲一個靜態文件的HTTP響應頭增長了如下標記: ETag: "74177-b-46585209c1bc0" 瀏覽器得到這個內容的ETag後,便會在下次請求該內容時,在HTTP請求頭中附加如下標記來詢問服務器該內容是否發生變化: If-None-Match: "74177-b-46585209c1bc0" 這時服務器就須要從新計算這個內容的ETag值,並與HTTP請求中的ETag進行比較,若是相同的話,便返回304狀態碼,若是不一樣的話,則將最新的內容返回給瀏覽器。編碼

HTTP/1.1並無規定ETag的具體格式和計算方法,也就是說,Web服務器能夠自由定義ETag的格式和計算方法,好比一種簡單的方法是對文件內容計算md5值做爲ETag,總之只要可以起到標識內容的做用便可,ETag: "1944822255" 使用基於最後修改時間的緩存協商存在一些缺點,好比,有時候一些文件須要頻繁的更新,可是內容可能並無變化,那麼若是採用基於最後修改時間的緩存協商,那麼每次文件的修改時間變化後,不論內容是否真的變化,瀏覽器都會從新獲取所有內容;再好比,同一個文件存儲在多臺Web服務器上,用戶的請求在這些服務器之間輪詢,實現負載均衡,而這些服務器上同一個文件的最後修改時間很難保證徹底相同,這便會致使用戶的請求每次切換到新的服務器時就須要從新獲取全部內容。這時候,若是使用直接標記內容的某種ETag算法,就能夠避免這些問題。操作系統

##Expires HTTP中還有另外一個標記,那就是Expires,它告訴瀏覽器該內容在什麼時候過時,暗示瀏覽器在該內容過時以前不須要再詢問服務器,而直接使用本地緩存便可。 這樣的好處顯而易見,一旦瀏覽器絲絕不用請求服務器,那將徹底節省了帶寬和服務器處理等開銷,可謂皆大歡喜。 Expires標記更像善於放權的管理者,瀏覽器一旦看到某個內容附帶Expires標記後,便擁有了極大的權力,它無須在過時以前每次都詢問服務器,徹底能夠自做主張,而Last-Modified標記讓瀏覽器感到拘束,它們不得不每次都詢問服務器,即使它們認爲這樣作毫無心義。 Expires的格式相似於Last-Modified,它指示了內容過時的絕對時間,好比: Expires: Sun, 10 Feb 2002 16:00:00 GMT對於靜態內容,Web服務器在默認狀況下不會開啓Expires標記的支持,咱們須要進行必定的配置。code

##Cache-Control 經過Expires指定的過時時間,是來自於Web服務器的系統時間,若是用戶本地的時間和服務器時間不一致的話,那必定會影響到本地緩存的有效期檢查圖片

很容易想象,好比服務器端爲某個內容設置的過時時間爲1個小時,但是假如瀏覽器的時間比服務器晚了2個小時,那麼這個內容將被瀏覽器認爲當即過時。固然,通常咱們使用的操做系統(如Winddows)都會使用基於GMT的標準時間,而後本地時間經過時區來進行偏移計算,而HTTP中使用的也是GMT時間,因此通常不會由於時區而致使本地和服務器相差數個小時。可是,沒有人能保證用戶本地的時間都是與你的服務器一致的,甚至有時候你的服務器時間也許就是錯誤的,這些都會影響到瀏覽器緩存的正常工做,讓咱們的一片苦心付諸東流。md5

幸運的是,HTTP/1.1中還有一個標記用於彌補Expires的不足,那就是Cache-Control,它的格式以下所示: Cache-Control: max-age=<second> max-age指定了緩存過時的相對時間,單位是秒,而且這個時間是相對於瀏覽器本地時間而言。

對於靜態內容,事實上Web服務器在開啓Expires的同時,也會自動添加響應的Cache-Control標記,用於兼容HTTP/1.1,咱們來請求一個GIF圖片,它位於Apache服務器上,咱們爲Apache設置了GIF的過時策略,以下所示: ExpiresActive on ExpiresByType image/gif "access plus 1 hours" 接下來咱們在瀏覽器上請求這個圖片的URL,而後跟蹤HTTP響應頭,以下所示:

HTTP/1.1 200 OK
Date: Tue, 24 Mar 2009 04:51:03 GMT
Server: Apache/2.2.11 (Unix) PHP/5.2.1 DAV/2 SVN/1.4.3
Last-Modified: Wed, 27 Feb 2008 18:11:26 GMT
ETag: "7815c-303-44727bbbf0f80"
Accept-Ranges: bytes
Content-Length: 771
Cache-Control: max-age=3600
Expires: Tue, 24 Mar 2009 05:51:03 GMT
Keep-Alive: timeout=30, max=97
Connection: Keep-Alive
Content-Type: image/gif

能夠從以上頭信息中計算出,Expires時間恰好是Date時間以後的1個小時,同時,max-age的值爲3600秒。

值得一提的是,目前的主流瀏覽器都將HTTP/1.1做爲首選,因此當HTTP響應頭中同時含有Expires和Cache-Control時,瀏覽器會優先考慮Cache-Control。對於沒有Cache-Control的狀況,瀏覽器則會服從Expires的指示

##瀏覽器請求及緩存清理 對於主流瀏覽器,通常有如下三種請求頁面的方法: ###Ctrl+F5 這種方式能夠叫強制刷新,它使得網頁以及其中的全部組件都直接向Web服務器發送請求,而且不使用緩存協商,這樣的目的是獲取全部內容的最新版本 也能夠按住Ctrl鍵而後單擊瀏覽器的刷新按鈕得到一樣的結果。在實際使用中,不多有用戶會這樣操做。 ###F5 這種方式即是通常的刷新,咱們常用,它等同於單擊瀏覽器的刷新按鈕。它容許瀏覽器在請求中附加必要的緩存協商,但不容許瀏覽器直接使用本地緩存,也就是說,它可以讓Last-Modified發揮效果,可是對Expires無效。 ###單擊瀏覽器地址欄的「轉到」按鈕或者經過超連接跳到此頁 我想這種方式你們使用最多,還有一種操做也等同於這種方式,那就是在瀏覽器地址欄中輸入URL後按回車鍵,Firefox中經常使用這種方式,由於它沒有「轉到」按鈕。這幾種方式容許瀏覽器以最少的請求來獲取網頁的數據,瀏覽器會對全部沒有過時的內容直接使用本地緩存,因此,Expires標記只對這種方式有效,之後你不用在按了F5鍵後對瀏覽器沒有使用本地緩存感到奇怪。

相關文章
相關標籤/搜索