Etag

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主要在斷點下載時比較有用。

HTTP協定規格說明定義ETag為“被請求變數的實體值”。

另一種說法是,ETag是一個可以與Web資源關聯的記號(token)。典型的Web資源可以一個Web頁,但也可能是JSONXML文檔。伺服器單獨負責判斷記號是什麼及其含義,並在HTTP回響頭中將其傳送到客戶端,以下是伺服器端返回的格式:

ETag:"50b1c1d4f775c61:df3"

客戶端的查詢更新格式是這樣的:

If-None-Match : W / "50b1c1d4f775c61:df3"

如果ETag沒改變,則返回狀態304然後不返回,這也和Last-Modified一樣。

測試Etag主要在斷點下載時比較有用。

Last-Modified和ETags如何幫助提高性能?

聰明的開發者會把Last-Modified和ETags請求的http報頭一起使用,這樣可利用客戶端(例如瀏覽器)的快取。因為伺服器首先產生Last-Modified/Etag標記,伺服器可在稍後使用它來判斷頁面是否已經被修改。本質上,客戶端通過將該記號傳回伺服器要求伺服器驗證其(客戶端)快取。
過程如下:
1.客戶端請求一個頁面(A)。
2.伺服器返回頁面A,並在給A加上一個Last-Modified/ETag。
3.客戶端展現該頁面,並將頁面連同Last-Modified/ETag一起快取。
4.客戶再次請求頁面A,並將上次請求時伺服器返回的Last-Modified/ETag一起傳遞給伺服器。
5.伺服器檢查該Last-Modified或ETag,並判斷出該頁面自上次客戶端請求之後還未被修改,直接返迴響應304和一個空的回響體。

作用

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需要放在""內。

工作原理

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.(不要陷入到底使用誰的問題怪圈)

Apache中Etag實現

1.Apache首先判斷是不是弱Etag,這個留在下面講。如果不是,進入第二種情況:

強Etag根據配置檔案中的配置來設定Etag值,默認的Apache的FileEtag設定為:

FileEtag INode Mtime Size

也就是根據這三個屬性來生成Etag值,他們之間通過一些算法來實現,並輸出成hex的格式,相鄰屬性之間用-分隔,比如:

Etag"2e681a-6-5d044840"

這裡面的三個段,分別代表了INodeMTimeSize根據算法算出的值的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。

弱校驗(弱Etag)

重新考慮前面提到的3個問題:

問題1、一些檔案也許會周期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認為這個檔案被修改了,而重新GET;

解決辦法:如果使用強Etag,每次得會要求重新GET頁面,如果使用Etag,比方說設定成 File Etag Size 等,就可以忽略 MTime 造成的 Last-Modified 時間修改從而影響了 If-Modified-Since(IMS) 這個校驗了。這點和弱Etag無關。

問題2、某些檔案修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒)

解決辦法:如果是這種情況,Apache會自動判斷請求時間和修改時間之間的差值,如果小於1s,Apache會認為這個檔案在這1秒內可能會再次被修改,因此生成一個弱Etag(WeakEtag),這個Etag僅僅基於MTime來生成,因此MTime只能精確到s,所以1s內生成的Etag總是一樣,這樣就避免了使用強Etag造成的1s內頻繁的刷新Cache的情況。(貌似不用Etag,僅僅使用Last-Modified就可以解決,但是這針對的僅僅是修改超級頻繁的情況,很多檔案可能同時也使用強Etag驗證)。弱Etag以W/開始,比如:W/"2e681a"

問題3、某些伺服器不能精確的得到檔案的最後修改時間;

解決辦法:生成Etag,因為Etag可以綜合Inode,MTime和Size,可以避免這個問題

相關詞條

相關搜尋

熱門詞條