Nginx Etag學習

Nginx Etag

什麼是Etag

Etag其實是一個頁面的Hash值,當瀏覽器刷新頁面的時候,瀏覽器會發送頁面的Etag值,讓服務器進行比較,服務器如果發現eTag值沒變,則返回304,瀏覽器則從緩存中獲取頁面,如果不相等,則重新獲取頁面,
如果eTag過期,則重新獲取頁面。

Last-Modified / If-Modified-Since

當請求一個頁面時,如果瀏覽器使用本地緩存,因此我們經常會看到一個HTTP請求爲304狀態。或者顯示200狀態,在chrome下標註是from cache,在火狐下會標註BFCache;

我們希望在服務器端更新了靜態文件(如css、js、圖片),能夠在客戶端得到及時的更新,但又不想讓瀏覽器每次請求都從服務器端獲取靜態資源。那麼就需要用到Last-Modified/if-Modified-Since

當瀏覽器第一次請求一個url時,服務器端的返回狀態碼爲200,同時HTTP響應頭會有一個Last-Modified標記着文件在服務器端最後被修改的時間
在這裏插入圖片描述
覽器第二次請求上次請求過的url時,瀏覽器會在HTTP請求頭添加一個If-Modified-Since的標記,用來詢問服務器該時間之後文件是否被修改過.
在這裏插入圖片描述
如果服務器端的資源沒有變化,則自動返回304狀態,使用瀏覽器緩存,從而保證了瀏覽器不會重複從服務器端獲取資源,也保證了服務器有變化是,客戶端能夠及時得到最新的資源。

Etag工作原理

當瀏覽器第一次請求一個url時,服務器端的返回狀態碼爲200,同時HTTP響應頭會有一個Etag,存放着服務器端生成的一個序列值
在這裏插入圖片描述
瀏覽器第二次請求上次請求過的url時,瀏覽器會在HTTP請求頭添加一個If-None-Match的標記,用來詢問服務器該文件有沒有被修改。
在這裏插入圖片描述

爲什麼要使用Etag

Etag主要爲了解決Last-Modified無法解決的一些問題

  1. 一些文件也許會週期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認爲這個文件被修改了,而重新GET;
  2. 某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒)
  3. 某些服務器不能精確的得到文件的最後修改時間;

爲此,HTTP/1.1引入了Etag(EntityTags)

Etag字符含義

Etag"2e681a-6-5d044840"
這裏面的三個段,分別代表了INode,MTime,Size根據算法算出的值的Hex格式(不要誤以爲Etag就是固定的3段式)

強Etag和弱Etag

強Etag根據配置文件中的配置來設置Etag值,默認的Apache的FileEtag設置爲:
FileEtag INode Mtime Size
也就是根據這三個屬性來生成Etag值,他們之間通過一些算法來實現,並輸出成hex的格式,相鄰屬性之間用-分隔,比如:Etag “2e681a-6-5d044840”

弱Etag是在前面加個W/
如下形式

強ETag表示形式:"22FAA065-2664-4197-9C5E-C92EA03D0A16"。

弱ETag表現形式:w/"22FAA065-2664-4197-9C5E-C92EA03D0A16"。

強、弱ETag類型的出現與Apache服務器計算ETag的方式有關。Apache默認通過FileEtag中FileEtag INode Mtime Size的配置自動生成ETag(當然也可以通過用戶自定義的方式)。

假設服務端的資源頻繁被修改(如1秒內修改了N次),此時如果有用戶將Apache的配置改爲MTime,由於MTime只能精確到秒,那麼就可以避免強ETag在1秒內的ETag總是不同而頻繁刷新Cache(如果資源在秒級經常被修改,也可以通過Last-Modified來解決)。

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

Etag丟失問題

nginx 在開啓了 gzip 之後,如果有 ETAG 則會調用 ngx_http_clear_etag 將其清除。從 nginx 1.7.3 這個版本之後,nginx 不再強硬地清除 ETAG 了,而是換了一種 weak ETAG 的策略。

Etag配置

nginx是默認開始etag的。
關閉

etag off;

Etag帶來的問題

ETag的問題在於通常使用某些屬性來構造它,有些屬性對於特定的部署了網站的服務器來說是唯一的。當使用集羣服務器的時候,瀏覽器從一臺服務器上獲取了原始組件,之後又向另外一臺不同的服務器發起條件GET請求,ETag就會出現不匹配的狀況。

解決思路:

  1. 如果使用Last-Modified不會出現任何問題,可以直接移除ETag,google的搜索首頁則沒有使用ETag。

  2. 確定要使用ETag,在配置ETag的值的時候,移除可能影響到組件集羣服務器驗證的屬性,例如只包含組件大小和時間戳。

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