HTTP协议Etag详解
HTTP協(xié)議規(guī)格說(shuō)明定義ETag為“被請(qǐng)求變量的實(shí)體值”。
另一種說(shuō)法是,ETag是一個(gè)可以與Web資源關(guān)聯(lián)的記號(hào)(token)。典型的Web資源可以一個(gè)Web頁(yè),但也可能是JSON或XML文檔。服務(wù)器單獨(dú)負(fù)責(zé)判斷記號(hào)是什么及其含義,并在HTTP響應(yīng)頭中將其傳送到客戶端,以下是服務(wù)器端返回的格式:
ETag:"50b1c1d4f775c61:df3"
客戶端的查詢(xún)更新格式是這樣的:
If-None-Match : W / "50b1c1d4f775c61:df3"
如果ETag沒(méi)改變,則返回狀態(tài)304然后不返回,這也和Last-Modified一樣。
測(cè)試Etag主要在斷點(diǎn)下載時(shí)比較有用。
Etag - Last-Modified和Etags如何幫助提高性能?
聰明的開(kāi)發(fā)者會(huì)把Last-Modified和ETags請(qǐng)求的http報(bào)頭一起使用,這樣可利用客戶端(例如瀏覽器)的緩存。因?yàn)榉?wù)器首先產(chǎn)生Last-Modified/Etag標(biāo)記,服務(wù)器可在稍后使用它來(lái)判斷頁(yè)面是否已經(jīng)被修改。本質(zhì)上,客戶端通過(guò)將該記號(hào)傳回服務(wù)器要求服務(wù)器驗(yàn)證其(客戶端)緩存。
過(guò)程如下:
1.客戶端請(qǐng)求一個(gè)頁(yè)面(A)。
2.服務(wù)器返回頁(yè)面A,并在給A加上一個(gè)Last-Modified/ETag。
3.客戶端展現(xiàn)該頁(yè)面,并將頁(yè)面連同Last-Modified/ETag一起緩存。
4.客戶再次請(qǐng)求頁(yè)面A,并將上次請(qǐng)求時(shí)服務(wù)器返回的Last-Modified/ETag一起傳遞給服務(wù)器。
5.服務(wù)器檢查該Last-Modified或ETag,并判斷出該頁(yè)面自上次客戶端請(qǐng)求之后還未被修改,直接返回響應(yīng)304和一個(gè)空的響應(yīng)體。
Etag - 作用
Etag 主要為了解決 Last-Modified 無(wú)法解決的一些問(wèn)題。
1、一些文件也許會(huì)周期性的更改,但是他的內(nèi)容并不改變(僅僅改變的修改時(shí)間),這個(gè)時(shí)候我們并不希望客戶端認(rèn)為這個(gè)文件被修改了,而重新GET;
2、某些文件修改非常頻繁,比如在秒以下的時(shí)間內(nèi)進(jìn)行修改,(比方說(shuō)1s內(nèi)修改了N次),If-Modified-Since能檢查到的粒度是s級(jí)的,這種修改無(wú)法判斷(或者說(shuō)UNIX記錄MTIME只能精確到秒)
3、某些服務(wù)器不能精確的得到文件的最后修改時(shí)間;
為此,HTTP/1.1?引入了 Etag(Entity Tags).Etag僅僅是一個(gè)和文件相關(guān)的標(biāo)記,可以是一個(gè)版本標(biāo)記,比如說(shuō)v1.0.0或者說(shuō)"2e681a-6-5d044840"這么一串看起來(lái) 很神秘的編碼。但是HTTP/1.1標(biāo)準(zhǔn)并沒(méi)有規(guī)定Etag的內(nèi)容是什么或者說(shuō)要怎么實(shí)現(xiàn),唯一規(guī)定的是Etag需要放在""內(nèi)。
Etag - 工作原理
Etag由服務(wù)器端生成,客戶端通過(guò)If-Match或者說(shuō)If-None-Match這個(gè)條件判斷請(qǐng)求來(lái)驗(yàn)證資源是否修改。常見(jiàn)的是使用If-None-Match.請(qǐng)求一個(gè)文件的流程可能如下:
====第一次請(qǐng)求===
1.客戶端發(fā)起 HTTP GET 請(qǐng)求一個(gè)文件;
2.服務(wù)器處理請(qǐng)求,返回文件內(nèi)容和一堆Header,當(dāng)然包括Etag(例如"2e681a-6-5d044840")(假設(shè)服務(wù)器支持Etag生成和已經(jīng)開(kāi)啟了Etag).狀態(tài)碼200
====第二次請(qǐng)求===
1.客戶端發(fā)起 HTTP GET 請(qǐng)求一個(gè)文件,注意這個(gè)時(shí)候客戶端同時(shí)發(fā)送一個(gè)If-None-Match頭,這個(gè)頭的內(nèi)容就是第一次請(qǐng)求時(shí)服務(wù)器返回的Etag:2e681a-6-5d044840
2.服務(wù)器判斷發(fā)送過(guò)來(lái)的Etag和計(jì)算出來(lái)的Etag匹配,因此If-None-Match為False,不返回200,返回304,客戶端繼續(xù)使用本地緩存;
流程很簡(jiǎn)單,問(wèn)題是,如果服務(wù)器又設(shè)置了Cache-Control:max-age和Expires呢,怎么辦?
答案是同時(shí)使用,也就是說(shuō)在完全匹配If-Modified-Since和If-None-Match即檢查完修改時(shí)間和Etag之后,服務(wù)器才能返回304.(不要陷入到底使用誰(shuí)的問(wèn)題怪圈)
Etag - Apache中Etag實(shí)現(xiàn)
1.Apache首先判斷是不是弱Etag,這個(gè)留在下面講。如果不是,進(jìn)入第二種情況:
強(qiáng)Etag根據(jù)配置文件中的配置來(lái)設(shè)置Etag值,默認(rèn)的Apache的FileEtag設(shè)置為:
FileEtag INode Mtime Size
也就是根據(jù)這三個(gè)屬性來(lái)生成Etag值,他們之間通過(guò)一些算法來(lái)實(shí)現(xiàn),并輸出成hex的格式,相鄰屬性之間用-分隔,比如:
Etag"2e681a-6-5d044840"
這里面的三個(gè)段,分別代表了INode,MTime,Size根據(jù)算法算出的值的Hex格式,(如果在這里看到了非Hex里面的字符(也就是0-f),那你可能看見(jiàn)神了:))
當(dāng)然,可以改變Apache的FileEtag設(shè)置,比如設(shè)置成FileEtagSize,那么得到的Etag可能為:
Etag"6"
總之,設(shè)置了幾個(gè)段,Etag值就有幾個(gè)段。(不要誤以為Etag就是固定的3段式)
說(shuō)明
這里說(shuō)的都是Apache2.2里面的Etag實(shí)現(xiàn),因?yàn)镠TTP/1.1并沒(méi)有規(guī)定Etag必須是什么樣的實(shí)現(xiàn)或者格式,因此,也可 以修改或者完全編寫(xiě)自己的算法得到Etag,比如"2e681a65d044840",客戶端會(huì)記住并緩存下這個(gè)Etag(Windows里面保存在哪 里,下次訪問(wèn)的時(shí)候直接拿這個(gè)值去和服務(wù)器生成的Etag對(duì)比。
注意
不管怎么樣的算法,在服務(wù)器端都要進(jìn)行計(jì)算,計(jì)算就有開(kāi)銷(xiāo),會(huì)帶來(lái)性能損失。因此為了榨干這一點(diǎn)點(diǎn)性能,不少網(wǎng)站完全把Etag禁用了(比如Yahoo!),這其實(shí)不符合HTTP/1.1的規(guī)定,因?yàn)镠TTP/1.1總是鼓勵(lì)服務(wù)器盡可能的開(kāi)啟Etag。
Etag - 弱校驗(yàn)(弱Etag)
重新考慮前面提到的3個(gè)問(wèn)題:
問(wèn)題1、一些文件也許會(huì)周期性的更改,但是他的內(nèi)容并不改變(僅僅改變的修改時(shí)間),這個(gè)時(shí)候我們并不希望客戶端認(rèn)為這個(gè)文件被修改了,而重新GET;
解決辦法:如果使用強(qiáng)Etag,每次得會(huì)要求重新GET頁(yè)面,如果使用Etag,比方說(shuō)設(shè)置成 File Etag Size 等,就可以忽略 MTime 造成的 Last-Modified 時(shí)間修改從而影響了 If-Modified-Since(IMS) 這個(gè)校驗(yàn)了。這點(diǎn)和弱Etag無(wú)關(guān)。
問(wèn)題2、某些文件修改非常頻繁,比如在秒以下的時(shí)間內(nèi)進(jìn)行修改,(比方說(shuō)1s內(nèi)修改了N次),If-Modified-Since能檢查到的粒度是s級(jí)的,這種修改無(wú)法判斷(或者說(shuō)UNIX記錄MTIME只能精確到秒)
解決辦法:如果是這種情況,Apache會(huì)自動(dòng)判斷請(qǐng)求時(shí)間和修改時(shí)間之間的差值,如果小于1s,Apache會(huì)認(rèn)為這個(gè)文件在這1秒內(nèi)可能會(huì)再次被修改, 因此生成一個(gè)弱Etag(WeakEtag),這個(gè)Etag僅僅基于MTime來(lái)生成,因此MTime只能精確到s,所以1s內(nèi)生成的Etag總是一樣, 這樣就避免了使用強(qiáng)Etag造成的1s內(nèi)頻繁的刷新Cache的情況。(貌似不用Etag,僅僅使用Last-Modified就可以解決,但是這針對(duì)的 僅僅是修改超級(jí)頻繁的情況,很多文件可能同時(shí)也使用強(qiáng)Etag驗(yàn)證)。弱Etag以W/開(kāi)始,比如:W/"2e681a"
問(wèn)題3、某些服務(wù)器不能精確的得到文件的最后修改時(shí)間;
解決辦法:生成Etag,因?yàn)镋tag可以綜合Inode,MTime和Size,可以避免這個(gè)問(wèn)題
轉(zhuǎn)載于:https://www.cnblogs.com/flysnow-z/archive/2012/08/17/2644420.html
總結(jié)
以上是生活随笔為你收集整理的HTTP协议Etag详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 问天问大地是什么歌呢?
- 下一篇: 如果你喜欢一个程序员小伙