
ETag(Entity Tag 的縮寫)意思是是實(shí)體標(biāo)簽。是HTTP1.1規(guī)范中新增的一個(gè)HTTP頭信息,也即是請(qǐng)求HEAD中的一個(gè)屬性。ETagHTTP響應(yīng)頭是資源的特定版本的標(biāo)識(shí)符。這可以讓緩存更高效,并節(jié)省帶寬,因?yàn)槿绻麅?nèi)容沒有改變,Web服務(wù)器不需要發(fā)送完整的響應(yīng)。而如果內(nèi)容發(fā)生了變化,使用ETag有助于防止資源的同時(shí)更新相互覆蓋(“空中碰撞”)。
如果給定URL中的資源更改,則一定要生成新的Etag值。 因此Etags類似于指紋,也可能被某些服務(wù)器用于跟蹤。 比較Etags能快速確定此資源是否變化,但也可能被跟蹤服務(wù)器永久存留。
ETag的語法如下:
ETag: W/"<etag_value>"
ETag: "<etag_value>"
'W/'(大小寫敏感) 表示使用弱驗(yàn)證器。 弱驗(yàn)證器很容易生成,但不利于比較。 強(qiáng)驗(yàn)證器是比較的理想選擇,但很難有效地生成。 相同資源的兩個(gè)弱Etag值可能語義等同,但不是每個(gè)字節(jié)都相同。
"<etag_value>"實(shí)體標(biāo)簽唯一地表示所請(qǐng)求的資源。 它們是位于雙引號(hào)之間的ASCII字符串(如“675af34563dc-tr34”)。 沒有明確指定生成ETag值的方法。 通常,使用內(nèi)容的散列,最后修改時(shí)間戳的哈希值,或簡(jiǎn)單地使用版本號(hào)。 例如,MDN使用wiki內(nèi)容的十六進(jìn)制數(shù)字的哈希值。
當(dāng)瀏覽器請(qǐng)求服務(wù)器的某項(xiàng)資源(A)時(shí), 服務(wù)器根據(jù)A算出一個(gè)哈希值(3f80f-1b6-3e1cb03b)并通過 ETag 返回給瀏覽器,瀏覽器把"3f80f-1b6-3e1cb03b" 和 A 同時(shí)緩存在本地,當(dāng)下次再次向服務(wù)器請(qǐng)求A時(shí),會(huì)通過類似 If-None-Match: "3f80f-1b6-3e1cb03b" 的請(qǐng)求頭把ETag發(fā)送給服務(wù)器,服務(wù)器再次計(jì)算A的哈希值并和瀏覽器返回的值做比較,如果發(fā)現(xiàn)A發(fā)生了變化就把A返回給瀏覽器(200),如果發(fā)現(xiàn)A沒有變化就給瀏覽器返回一個(gè)304未修改。這樣通過控制瀏覽器端的緩存,可以節(jié)省服務(wù)器的帶寬,因?yàn)榉?wù)器不需要每次都把全量數(shù)據(jù)返回給客戶端。
服務(wù)器在檢測(cè)緩存的組件是否和原始服務(wù)器上的組件匹配時(shí)通常有兩種方式:一是比較最新修改日期(Last-Modefied Date); 二是比較實(shí)體標(biāo)簽。
上面介紹了ETag的原理,接下來介紹關(guān)于比較最新修改日期的方式。比較最新修改日期時(shí)瀏覽器會(huì)使用If-Modified-Since頭將最新修改日期與原始服務(wù)器進(jìn)行比較,如果服務(wù)器上組件的最新修改日期與瀏覽器傳回的值匹配,那么客戶端將繼續(xù)使用本地緩存,不解析服務(wù)器返回的值,并且HTTP的狀態(tài)碼返回為304,這樣可以節(jié)約組件下載的時(shí)間。如果最新修改時(shí)間不同,那么客戶端重新解析服務(wù)器,并獲取服務(wù)器上的組件,此時(shí)返回的HTTP狀態(tài)碼為200。見圖所示

Last-Modified與Etag類似。不過Last-Modified表示響應(yīng)資源在服務(wù)器最后修改時(shí)間而已。與Etag相比,不足為:
Last-Modified與Etag類似,之所以還要使用ETag是因?yàn)長(zhǎng)ast-Modified存在一些缺點(diǎn):
1) Last-Modified用于標(biāo)注的最后修改的時(shí)間,但其只能精確到秒,如果某個(gè)文件在1秒鐘以內(nèi),被修改多次的話,Last-Modified將不能準(zhǔn)確標(biāo)注出文件的修改時(shí)間;
2) 如果一些文件只是被定期的將時(shí)間修改了,而文件內(nèi)容并沒有任何變化時(shí),Last-Modified還是會(huì)認(rèn)為這個(gè)文件更新了,這樣這個(gè)文件就必須從服務(wù)器端重新獲取,而不無法使用緩存。
3) 如果服務(wù)器沒有準(zhǔn)確獲取文件修改時(shí)間,或者與代理服務(wù)器時(shí)間不一致時(shí),這樣Last-Modified就無法精確的判斷了,但使用ETag可以準(zhǔn)確的判斷。
ETag的問題在于通常使用某些屬性來構(gòu)造它,有些屬性對(duì)于特定的部署了網(wǎng)站的服務(wù)器來說是唯一的。當(dāng)使用集群服務(wù)器的時(shí)候,瀏覽器從一臺(tái)服務(wù)器上獲取了原始組件,之后又向另外一臺(tái)不同的服務(wù)器發(fā)起條件GET請(qǐng)求,ETag就會(huì)出現(xiàn)不匹配的狀況。
所以如果Last-Modified可能解決組件修改的問題,那么就不要使用ETag,直接移除即可。如果確定要使用ETag,在配置ETag的值的時(shí)候,移除可能影響到組件集群服務(wù)器驗(yàn)證的屬性,例如只包含組件大小和時(shí)間戳。