複製鏈接
請複製以下鏈接發送給好友

ETag

鎖定
HTTP協議規格説明定義ETag為“被請求變量的實體值”。另一種説法是,ETag是一個可以與Web資源關聯的記號(token)。典型的Web資源可以一個Web頁,但也可能是JSON或XML文檔。服務器單獨負責判斷記號是什麼及其含義,並在HTTP響應頭中將其傳送到客户端,以下是服務器端返回的格式:ETag:50b1c1d4f775c61:df3客户端的查詢更新格式是這樣的:If-None-Match : W / 50b1c1d4f775c61:df3如果ETag沒改變,則返回狀態304然後不返回,這也和Last-Modified一樣。測試Etag主要在斷點下載時比較有用。
中文名
ETag
概    念
Etag是URL的Entity Tag
性    能
聰明的服務器開發者
原    理
請求流程

目錄

ETag概念

Etag 是URL的Entity Tag,用於標示URL對象是否改變,區分不同語言和Session等等。具體內部含義是使服務器控制的,就像Cookie那樣。

ETag性能

聰明的服務器開發者會把ETags和GET請求的“If-None-Match”頭一起使用,這樣可利用客户端(例如瀏覽器)的緩存。因為服務器首先產生ETag,服務器可在稍後使用它來判斷頁面是否已經被修改。本質上,客户端通過將該記號傳回服務器要求服務器驗證其(客户端)緩存。
其過程如下:
客户端請求一個頁面(A)。 服務器返回頁面A,並在給A加上一個ETag。 客户端展現該頁面,並將頁面連同ETag一起緩存。 客户再次請求頁面A,並將上次請求時服務器返回的ETag一起傳遞給服務器。 服務器檢查該ETag,並判斷出該頁面自上次客户端請求之後還未被修改,直接返回響應304(未修改——Not Modified)和一個空的響應體。

ETag優勢

1、有些URL是多語言的網頁,相同的URL會返回不同的東東。還有不同的Session有不同的Cookie也就有不同的內容。這種情況下如果過 Proxy,Proxy就無法區分導致串門,只能簡單的取消cache功能。Etag解決了這個問題,因為它能區分相同URL不同的對象。
2、老的HTTP標準裏有個Last-Modified+If-Modified-Since表明URL對象是否改變。Etag也具有這種功能,因為對象改變也造成Etag改變,並且它的控制更加準確。Etag有兩種用法 If-Match/If-None-Match,就是如果服務器的對象和客户端的對象ID(不)匹配才執行。這裏的If-Match/If-None- Match都能一次提交多個Etag。If-Match可以在Etag未改變時斷線重傳。If-None-Match可以刷新對象(在有新的Etag時返回)。
3、Etag中有種Weak Tag,值為 W/"xxxxx"。他聲明Tag是弱匹配的,只能做模糊匹配,在差異達到一定閾值時才起作用。
4、Etag對於cache CGI頁面很有用。特別是論壇,論壇有辦法為每個帖子頁面生成唯一的Etag,在帖子未改變時,查看話題屬性比較Etag就能避免刷新帖子,減少CGI操作和網絡傳輸。比如論壇中看帖就返回Etag,減少論壇負擔。
5、Etag在不同URL之間沒有可比性,也就是不同URL相同Etag沒有特別意義。 [1] 

ETag請求流程

Etag由服務器端生成,客户端通過If-Match或者説If-None-Match這個條件判斷請求來驗證資源是否修改。常見的是使用If-None-Match.請求一個文件的流程可能如下:
====第一次請求===
1.客户端發起 HTTP GET 請求一個文件;
2.服務器處理請求,返回文件內容和一堆Header,當然包括Etag(例如"2e681a-6-5d044840")(假設服務器支持Etag生成和已經開啓了Etag).狀態碼200
====第二次請求===
1.客户端發起 HTTP GET 請求一個文件,注意這個時候客户端同時發送一個If-None-Match頭,這個頭的內容就是第一次請求時服務器返回的Etag:2e681a-6-5d044840
2.服務器判斷髮送過來的Etag和計算出來的Etag匹配,因此If-None-Match為False,不返回200,返回304,客户端繼續使用本地緩存
流程很簡單,問題是,如果服務器又設置了Cache-Control:max-age和Expires呢,怎麼辦?
答案是同時使用,也就是説在完全匹配If-Modified-Since和If-None-Match即檢查完修改時間和Etag之後,服務器才能返回304.(不要陷入到底使用誰的問題怪圈) [2] 

ETag作用

Etag 主要為了解決 Last-Modified 無法解決的一些問題。
1、一些文件也許會週期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客户端認為這個文件被修改了,而重新GET;
2、某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方説1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者説UNIX記錄MTIME只能精確到秒)
3、某些服務器不能精確的得到文件的最後修改時間;
為此,HTTP/1.1引入了 Etag(Entity Tags).Etag僅僅是一個和文件相關的標記,可以是一個版本標記,比如説v1.0.0或者説"2e681a-6-5d044840"這麼一串看起來很神秘的編碼。但是HTTP/1.1標準並沒有規定Etag的內容是什麼或者説要怎麼實現,唯一規定的是Etag需要放在""內。 [1] 

ETagApache

Apache首先判斷是不是弱Etag,這個留在下面講。如果不是,進入第二種情況:
強Etag根據配置文件中的配置來設置Etag值,默認的Apache的FileEtag設置為:
FileEtag INode Mtime Size
也就是根據這三個屬性來生成Etag值,他們之間通過一些算法來實現,並輸出成hex的格式,相鄰屬性之間用-分隔,比如:
Etag"2e681a-6-5d044840"
這裏面的三個段,分別代表了INode,MTime,Size根據算法算出的值的Hex格式,(如果在這裏看到了非Hex裏面的字符(也就是0-f),那你可能看見神了:))
當然,可以改變Apache的FileEtag設置,比如設置成FileEtagSize,那麼得到的Etag可能為:
Etag"6"
總之,設置了幾個段,Etag值就有幾個段。(不要誤以為Etag就是固定的3段式)
説明:這裏説的都是Apache2.2裏面的Etag實現,因為HTTP/1.1並沒有規定Etag必須是什麼樣的實現或者格式,因此,也可以修改或者完全編寫自己的算法得到Etag,比如"2e681a65d044840",客户端會記住並緩存下這個Etag(Windows裏面保存在哪裏,下次訪問的時候直接拿這個值去和服務器生成的Etag對比。
注意:不管怎麼樣的算法,在服務器端都要進行計算,計算就有開銷,會帶來性能損失。因此為了榨乾這一點點性能,不少網站完全把Etag禁用了(比如Yahoo!),這其實不符合HTTP/1.1的規定,因為HTTP/1.1總是鼓勵服務器儘可能的開啓Etag。 [2] 
參考資料
  • 1.    Sen, Dipankar; Sen, Prosenjit; Das, Anand M., RFID For Energy and Utility Industries, PennWell, 2009, ISBN 978-1-59370-105-5
  • 2.    Weis, Stephen A., RFID (Radio Frequency Identification): Principles and Applications, MIT CSAIL, 2007