Etag、Expires、Last-Modified

本文對頁面中Etag和Expires標識處理,使得頁面更加有效被Cache。

在客戶端通過瀏覽器發出第一次請求某一個URL時,根據 HTTP 協議的規定,瀏覽器會向服務器傳送報頭(Http Request Header),服務器端響應同時記錄相關屬性標記(Http Reponse Header),服務器端的返回狀態會是200,格式類似如下:
HTTP/1.1 200 OK
Date: Tue, 03 Mar 2009 04:58:40 GMT
Content-Type: image/jpeg
Content-Length: 83185
Last-Modified: Tue, 24 Feb 2009 08:01:04 GMT
Cache-Control: max-age=2592000

Expires: Thu, 02 Apr 2009 05:14:08 GMT
Etag: "5d8c72a5edda8d6a:3239″

客戶端第二次請求此URL時,根據 HTTP 協議的規定,瀏覽器會向服務器傳送報頭(Http Request Header),服務器端響應並記錄相關記錄屬性標記文件沒有發生改動,服務器端返回304,直接從緩存中讀取:
HTTP/1.x 304 Not Modified
Date: Tue, 03 Mar 2009 05:03:56 GMT
Content-Type: image/jpeg
Content-Length: 83185
Last-Modified: Tue, 24 Feb 2009 08:01:04 GMT
Cache-Control: max-age=2592000
Expires: Thu, 02 Apr 2009 05:14:08 GMT
Etag: "5d8c72a5edda8d6a:3239″
其中Last-ModifiedExpiresEtag是標記頁面緩存標識

一、Last-Modified、Expires和Etag相關工作原理
1、Last-Modified
在瀏覽器第一次請求某一個URL時,服務器端的返回狀態會是200,內容是你請求的資源,同時有一個Last-Modified的屬性標記(Http Reponse Header)此文件在服務期端最後被修改的時間,格式類似這樣:
Last-Modified: Tue, 24 Feb 2009 08:01:04 GMT
客戶端第二次請求此URL時,根據 HTTP 協議的規定,瀏覽器會向服務器傳送 If-Modified-Since 報頭(Http Request Header),詢問該時間之後文件是否有被修改過:
If-Modified-Since: Tue, 24 Feb 2009 08:01:04 GMT
如果服務器端的資源沒有變化,則自動返回 HTTP 304 (NotChanged.)狀態碼,內容爲空,這樣就節省了傳輸數據量。當服務器端代碼發生改變或者重啓服務器時,則重新發出資源,返回和第一次請求時類似。從而保證不向客戶端重複發出資源,也保證當服務器有變化時,客戶端能夠得到最新的資源。
注:如果If-Modified-Since的時間比服務器當前時間(當前的請求時間request_time)還晚,會認爲是個非法請求

2、Etag工作原理
HTTP 協議規格說明定義ETag爲"被請求變量的實體標記" (參見14.19)。簡單點即服務器響應時給請求URL標記,並在HTTP響應頭中將其傳送到客戶端,類似服務器端返回的格式:
Etag: "5d8c72a5edda8d6a:3239″
客戶端的查詢更新格式是這樣的:
If-None-Match: "5d8c72a5edda8d6a:3239″
如果ETag沒改變,則返回狀態304。
即:在客戶端發出請求後,Http Reponse Header中包含 Etag: "5d8c72a5edda8d6a:3239″
標識,等於告訴Client端,你拿到的這個的資源有表示ID:5d8c72a5edda8d6a:3239。當下次需要發Request索要同一個URI的時候,瀏覽器同時發出一個If-None-Match報頭( Http RequestHeader)此時包頭中信息包含上次訪問得到的Etag: "5d8c72a5edda8d6a:3239″標識。
If-None-Match: "5d8c72a5edda8d6a:3239"
,這樣,Client端等於Cache了兩份,服務器端就會比對2者的etag。如果If-None-Match爲False,不返回200,返回304 (Not Modified) Response。

3、Expires
給出的日期/時間後,被響應認爲是過時。如Expires: Thu, 02 Apr 2009 05:14:08 GMT
需和Last-Modified結合使用。用於控制請求文件的有效時間,當請求數據在有效期內時客戶端瀏覽器從緩存請求數據而不是服務器端. 當緩存中數據失效或過期,才決定從服務器更新數據。


我們知道合理配置etag能節省不少帶寬。
事實上,配置etag緩存並沒有配置Last-Modified header 效果好。
當我們並不知道修改時間,Etag對動態內容還是比較有用。

手機之家高春輝關於etag補充:
幾個不同或者需要補充的地方:
1、“當然,Etag 對多數站點性能的影響並不是很大。”應該說 Etag 在正確使用的情況下,會讓大量的請求以 304 頭方式響應,可以相當的節省服務器資源和帶寬。之前一些地方寫的不要使用 Etag,是基於有些 webserver 的 Etag 的計算方法中包含了 inode,這在多臺web服務器的情況不可採用的,而改變這個計算方法就可以了。
2、對於儘早刷新這點,PHP 幾乎是做不到的。即使你執行了 flush 以及類似的函數,也要等到請求完全執行之後,纔會輸出給瀏覽器端。

3、AJAX 使用 GET 和 POST 各有好處,GET 方式可以更快響應,但是可能會有被瀏覽器緩存的問題,一般都需要加個隨機數來避免,POST 方式則不會。所以最好是根據自己的情況分別使用 GET 和 POST 方法。


擴展:HTTP中的緩存機制

網頁的緩存是由HTTP消息頭中的“Cache-control”來控制的,常見的取值有private、no-cache、max-age、must- revalidate等,默認爲private。其作用根據不同的重新瀏覽方式分爲以下幾種情況:

(1) 打開新窗口
值爲private、no-cache、must-revalidate,那麼打開新窗口訪問時都會重新訪問服務器。
而如果指定了max-age值,那麼在此值內的時間裏就不會重新訪問服務器,例如:
Cache-control: max-age=5(表示當訪問此網頁後的5秒 內再次訪問不會去服務器)

(2) 在地址欄回車
值爲private或must-revalidate則只有第一次訪問時會訪問服務器,以後就不再訪問。
值爲no-cache,那麼每次都會訪問。
值爲max-age,則在過期之前不會重複訪問。

(3) 按後退按扭
值爲private、must-revalidate、max-age,則不會重訪問,
值爲no-cache,則每次都重複訪問

(4) 按刷新按扭
 無論爲何值,都會重複訪問

Cache-control值爲“no-cache”時,訪問此頁面不會在Internet臨時文章夾留下頁面備份。


補充:

通常Last-Modified,Etag,Expire是一起混合使用的,特別是Last-Modified和Expire經常一起使用,因爲Expire可以讓瀏覽器完全不發起Http請求,而當瀏覽器強制F5的時候又有Last-Modified,這樣就很好的達到了瀏覽器段緩存的效果。

Etag和Expire一起使用時,先判斷Expire,如果已經過期,再發起Http請求,如果Etag也過期,則返回200響應。如果Etag沒有過期則返回304響應。

Last-Modified,Etag,Expires三個同時使用時。先判斷Expire,然後發送Http請求,服務器先判斷last-modified,再判斷Etag,必須都沒有過期,才能返回304響應。

ETag定義:RFC2616(也就是HTTP/1.1)中沒有說明ETag該是什麼格式的,只要確保用雙引號括起來就行了,所以你可以用文件的hash,甚至是直接用Last-Modified。

tomcat6默認支持etag,但是沒有expires。tomcat7中提供了expires filter。


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