http協議 - 淺談ETag

咱們都知道,HTTP/1.1中有一個Etag,用來判斷請求的文件是否被修改。
爲何要使用Etag呢?Etag主要爲了解決Last-Modified沒法解決的一些問題
一、一些文件也許會週期性的更改,可是他的內容並不改變(僅僅改變的修改時間),這個時候咱們並不但願客戶端認爲這個文件被修改了,而從新GET;
二、某些文件修改很是頻繁,好比在秒如下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改沒法判斷(或者說UNIX記錄MTIME只能精確到秒)
三、某些服務器不能精確的獲得文件的最後修改時間;

爲此,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"
這裏面的三個段,分別表明了INode,MTime,Size根據算法算出的值的Hex格式,(若是你在這裏看到了非Hex裏面的字符(也就是0-f),那你可能看見神了:))

固然,咱們能夠改變Apache的FileEtag設置,好比設置成FileEtag Size,那麼獲得的Etag可能爲:
Etag "6"
總之,設置了幾個段,Etag值就有幾個段。(不要誤覺得Etag就是固定的3段式)

說明
這裏說的都是Apache 2.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,比方說設置成FileEtag Size等,就能夠忽略MTime形成的Last-Modified時間修改從而影響了If-Modified-Since(IMS)這個校驗了。這點和 弱Etag無關。

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

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

問題三、某些服務器不能精確的獲得文件的最後修改時間;

解決辦法:生成Etag,由於Etag能夠綜合Inode,MTime和Size,能夠避免這個問題
相關文章
相關標籤/搜索