[CDN 技術] HTTP參數中Etag的重要性

這篇文章寫的挺好的,所以就轉載過來了,謝謝原作者的無私分享

[CDN 技術] HTTP參數中Etag的重要性    http2

Etag在HTTP1.1中有介紹,主要的作用就是在(css file, image, javascript file)文件後面添加一個唯一的參數(相當於查詢參數字符串),Etag有服務器端生成,並且隨着文件的改變而改變,這樣瀏覽器端就會只重新請求獲取 Etag發生變化的文件,減少瀏覽器端數據的流量,加快瀏覽器的反應速度,重要的是減輕服務器端的壓力,所以服務器端Etag的實現就比較重要了.

現在我們有個問題爲什麼要使用Etag呢?

Etag主要爲了解決Last-Modified無法解決的一些問題.他能比Last_Modified更加精確的知道文件是否被修改過.如果有個 文件修改非常頻繁,比如在秒以下的時間內進行修改,比如1秒內修改了10次,If-Modified-Since能檢查只能秒級的修改,所以這種修改無法 判斷.原因是UNIX記錄MTIME只能精確到秒.所以我們選擇生成Etag,因爲Etag可以綜合Inode,MTime和Size,可以避免這個問 題.

Etag的工作原理
Etag在服務器上生成後,客戶端通過If-Match或者說If-None-Match這個條件判斷請求來驗證資源是否修改.我們常見的是使用If-None-Match.請求一個文件的流程可能如下:
新的請求
客戶端發起HTTP GET請求一個文件(css ,image,js);服務器處理請求,返回文件內容和一堆Header(包括Etag,例如"2e681a-6-5d044840"),http頭狀態碼爲爲200.

同一個用戶第二次這個文件的請求
客戶端在一次發起HTTP GET請求一個文件,注意這個時候客戶端同時發送一個If-None-Match頭,這個頭中會包括上次這個文件的Etag(例如"2e681a- 6-5d044840"),這時服務器判斷髮送過來的Etag和自己計算出來的Etag,因此If-None-Match爲False,不返回200,返 回304,客戶端繼續使用本地緩存;

注意.服務器又設置了Cache-Control:max-age和Expires時,會同時使用,也就是說在完全匹配If-Modified-Since和If-None-Match即檢查完修改時間和Etag之後,服務器才能返回304.

下面是在Apache中的Etag的配置

在Apache中設置Etag的支持比較簡單,只需要在apache的配置中加入下面的內容就可以了:

FileETag MTime Size

註解:FileETag指令配置了當文檔是基於一個文件時用以創建ETag(實體標籤)應答頭的文件的屬性(ETag的值用於進行緩衝管理以節約網絡帶 寬).ETag的值由文件的inode(索引節點)、大小、最後修改時間決定.FileETag指令可以讓您選擇(如果您想進行選擇)這其中哪些要素將被 使用.主要關鍵字如下:

INode
    文件的索引節點(inode)數
MTime
    文件的最後修改日期及時間
Size
    文件的字節數
All
    所有存在的域,等價於:FileETag INode MTime Size
None
    如果一個文檔是基於文件的,則不在應答中包含任何ETag頭

在大型多WEB集羣時,使用ETag時有問題,所以有人建議使用WEB集羣時不要使用ETag,其實很好解決,因爲多服務器時,INode不一樣,所以不 同的服務器生成的ETag不一樣,所以用戶有可能重複下載(這時ETag就會不準),明白了上面的原理和設置後,解決方法也很容易,讓ETag後面二個參 數,MTime和Size就好了.只要ETag的計算沒有INode參於計算,就會很準了.


使用 HTTP 緩存

任何一個 WEB 項目,要提高性能,各個環節的緩存必不可少。利用好 HTTP 協議的緩存機制,可以大幅減少傳輸數據,減少請求,這又是一項收益投入比超高的優化手段。這裏把之前我寫的 HTTP/1.1 緩存機制介紹翻出來:

首先,服務端可以通過響應頭裏的 Last-Modified(最後修改時間) 或者 ETag(內容特徵) 標記實體。瀏覽器會存下這些標記,並在下次請求時帶上 If-Modified-Since: 上次 Last-Modified 的內容 或 If-None-Match: 上次 ETag 的內容,詢問服務端資源是否過期。如果服務端發現並沒有過期,直接返回一個狀態碼爲 304、正文爲空的響應,告知瀏覽器使用本地緩存;如果資源有更新,服務端返回狀態碼 200、新的 Last-Modified、Etag 和正文。這個過程被稱之爲 HTTP 的協商緩存,通常也叫做弱緩存。

可以看到協商緩存並不會節省連接數,但是在緩存生效時,會大幅減小傳輸內容(304 響應沒有正文,一般只有幾百字節)。另外爲什麼有兩個響應頭都可以用來實現協商緩存呢?這是因爲一開始用的 Last-Modified 有兩個問題:1)只能精確到秒,1 秒內的多次變化反映不出來;2)在輪詢的負載均衡算法中,如果各機器讀到的文件修改時間不一致,有緩存無故失效和緩存不更新的風險。HTTP/1.1 並沒有規定 ETag 的生成規則,而一般實現者都是對資源內容做摘要,能解決前面兩個問題。

另外一種緩存機制是服務端通過響應頭告訴瀏覽器,在什麼時間之前(Expires)或在多長時間之內(Cache-Control: Max-age=xxx),不要再請求服務器了。這個機制我們通常稱之爲 HTTP 的強緩存。

一旦資源命中強緩存規則後,再次訪問完全沒有 HTTP 請求(Chrome 開發者工具的 Network 面板依然會顯示請求,但是會註明 from cache;Firefox 的 firebug 也類似,會註明 BFCache),這會大幅提升性能。所以我們一般會對 CSS、JS、圖片等資源使用強緩存,而入口文件(HTML)一般使用協商緩存或不緩存,這樣可以通過修改入口文件中對強緩存資源的引入 URL 來達到即時更新的目的。

這裏也解釋下爲什麼有了 Expire,還要有 Cache-Control。也有兩個原因:1)Cache-Control 功能更強大,對緩存的控制能力更強;2)Cache-Control 採用的 max-age 是相對時間,不受服務端 / 客戶端時間不對的影響。

另外關於瀏覽器的刷新(F5 / cmd + r)和強刷(Ctrl + F5 / shift + cmd +r):普通刷新會使用協商緩存,忽略強緩存;強刷會忽略瀏覽器所有緩存(並且請求頭會攜帶 Cache-Control:no-cache 和 Pragma:no-cache,用來通知所有中間節點忽略緩存)。只有從地址欄或收藏夾輸入網址、點擊鏈接等情況下,瀏覽器纔會使用強緩存。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章