優化網站設計(十三):配置ETags


前言

網站設計的優化是一個很大的話題,有一些通用的原則,也有針對不同開發平台的一些建議。這方面的研究一直沒有停止過,我在不同的場合也分享過這樣的話題。

作為通用的原則,雅虎的工程師團隊曾經給出過35個最佳實踐。這個列表請參考  Best Practices for Speeding Up Your Web Site http://developer.yahoo.com/performance/rules.html,同時,他們還發布了一個相應的測試工具Yslow http://developer.yahoo.com/yslow/

我強烈推薦所有的網站開發人員都應該學習這些最佳實踐,並結合自己的實際項目情況進行應用。 接下來的一段時間,我將結合ASP.NET這個開發平台,針對這些原則,通過一個系列文章的形式,做些講解和演繹,以幫助大家更好地理解這些原則,並且更好地使用他們。

准備工作

為了跟隨我進行后續的學習,你需要准備如下的開發環境和工具

  1. Google Chrome 或者firefox ,並且安裝 Yslow這個擴展組件.請注意,這個組件是雅虎提供的,但目前沒有針對IE的版本。
    1. https://chrome.google.com/webstore/detail/yslow/ninejjcohidippngpapiilnmkgllmakh
    2. https://addons.mozilla.org/en-US/firefox/addon/yslow/
    3. 你應該對這些瀏覽器的開發人員工具有所了解,你可以通過按下F12鍵調出這個工具。
  2. Visaul Studio 2010 SP1 或更高版本,推薦使用Visual Studio 2012
    1. http://www.microsoft.com/visualstudio/eng/downloads
  3. 你需要對ASP.NET的開發基本流程和核心技術有相當的了解,本系列文章很難對基礎知識做普及。

本文要討論的話題

這一篇我和大家討論的是第十三條原則:Configure ETags (配置ETags)。

ETag,全稱為:Entity Tag,意思是實體標簽,從名字上看,是對於某種實體的一個標識。它屬於HTTP協議的一部分,也就是所有的Web服務器都應該(也確實能)支持這個特性。它的作用是用一個特殊的字符串來標識某個資源的“版本”,客戶端(瀏覽器)來請求的時候,可以比較,如果ETag一致,則表示該資源並沒有修改過,客戶端(瀏覽器)可以使用自己緩存的版本。

工作原理

我們通過實例來了解ETag的工作原理,當用戶第一次請求某個資源(通常為靜態資源)的時候

image

正常情況下,他將得到一個狀態碼為200的響應,並且在響應頭部中會包含一個ETag的信息(ETag    "6ab823201a4ece1:0")

image

【備注】這個值是我本機的IIS 8.0提供,不同的服務器可能會有所不同。我后面會解釋大致的含義。

 

接下來,如果用戶再次請求這個資源的話,瀏覽器會嘗試在請求頭部中包含這個信息,以便服務器可以比較,確定是要再次發送資源的內容。

image

我們注意這一行 If-None-Match    "6ab823201a4ece1:0"

然后,服務器會怎么樣響應這個請求呢?

image

服務器實際上是比較了ETag的值,它發現瀏覽器提供的值與該資源實際的值是一樣的,所以它就返回了304的狀態碼,而且不需要在響應的正文里面包含任何實際內容。瀏覽器得到304這個狀態碼之后,就知道該資源並沒有被修改,所以直接使用本地緩存的版本。

 

ETag的配置

在IIS產品家族中,新的版本(例如IIS 7以后的版本)會自動配置一個ETag,這個ETag的值很類似於下面這樣:

6ab823201a4ece1:0

它是由兩個部分組成的

  1. 第一部分稱為FileTimeStamp(時間戳),我們很容易聯想到這可能是跟文檔修改時間有關系,事實上確實是,但你無法將其直接還原為文檔修改時間(微軟並沒有公開這部分的算法)。我確實對此做過一些研究,但最終還是沒有辦法解釋這個值如何生成的,所以大家也只需要知道,這個是類似於一個時間戳的值就可以了。
  2. 第二部分為ChangeNumber(修改編號)。這個值在IIS 7.0以及后續的版本中,被統一設置為0。設置為一個統一值有利於解決一些問題(例如在服務器場模式下,該問題我后續也會討論到)。事實上,保留這個ChangeNumber我覺得主要是歷史遺留問題,因為早期版本是有這個值,而且可以不一樣。既然如果這個值不一樣的話,會給我們惹一些麻煩,那么其實最好的做法是干脆就不要這個字段了。但我想,為了保持格式上的一貫性,微軟最終保留了這個字段。

 

這個默認的ETag不需要任何的配置就會存在(反過來,你如果要刪除它倒是很不容易,這個問題后續也會提到),但我們可以繼續添加自己想要的特殊ETag。也就是說,對於一個資源,實際上是可以有多個ETag的。我們看看在IIS 中的設置。

image

image

你可以在這里設置任意的值。

我們可以預見到,如果這樣設置的話,那么在響應的頭部中應該就會有多個ETag了。如下圖所示

image

 

ETag與其他技術的比較

經過上面的介紹,大家應該知道ETag的功能,主要能提供對資源的版本標識,以避免無謂的重復下載。這從一定意義上,肯定是有利的,它可以提高性能。

如果這樣的話,那么它和“優化網站設計(三):對資源添加緩存控制” 中提到過的一些技術比較起來,有什么自己的特點呢?

響應標頭 優勢 和特點 劣勢 和可能的問題
Expires
  • HTTP 1.0就有,簡單易用。
  • 服務器通過這個Header告訴瀏覽器,某資源直到某個時間才會過期,所以在沒有過期之前,瀏覽器就直接使用本地的緩存了。
  • 因為這是時間是由服務器發送的(UTC),但如果服務器時間和客戶端事件存在不一致,可能會有些問題。
  • 可能存在版本的問題,因為如果在到期之前修改過了,客戶端是不會知道的。
  • Cache-Control中的max-age可以實現類似的效果,但更加好,因為max-age是一個以秒為單位的時間數,而不是具體的時間,所以不存在上面提到的第一個問題。

Cache-Control

  • 服務器通過一個Header(Last-Modified)告訴瀏覽器,某資源最后修改的時間
  • 瀏覽器在請求的時候,包含一個Header(If-Modified-Since),然后服務器可以進行比較,如果在該時間后沒有修改過,則返回304
  • 它比Expires多很多選項設置
  • Last-Modified 也是一個時間,但該時間只能精確到秒,如果在同一個秒中有多次修改(這個在現在的環境下應該確實是可能的),則可能會發生問題。
ETag
  • 可以更加精確地判斷資源是否被修改,因為它不是一個時間值,而是對時間經過處理的一個長整型數值(當然具體算法我們目前還不得而知)
  • 瀏覽器發起新請求時需要包含 If-None-Match
  • 如果部署在服務器場環境中,配置不當的話,可能每個服務器會對相同的資源生成不一樣的ETag,這樣就增加了重復下載的可能性。要理解這個問題的原因,以及如何解決,請參考這里的文檔:http://support.microsoft.com/kb/922703/en-us
  • 該問題在IIS 7以及以后的版本中應該不存在了

這幾個技術其實很多時候是會結合起來用的,而且優先級也有所不同。通常,ETag是優先於Cache-Control的,而Cache-Control又是優先於Expires的

clip_image006

 

 

何時以及如何刪除ETag的功能?

由於之前談到可能的一些問題,雅虎團隊在當年寫這個原則的時候,是建議在服務器場的環境下面禁用ETag的,在Apache中,可以通過修改配置文件來實現。而在IIS 中,如果你所使用的是7.0以及后續的版本,實際上應該可以不禁用,因為現在不會存在他們所提到的那個問題了。但如果你真的想要了解一下如何禁用,那么請參考下面的操作

  1. 安裝這個擴展:http://www.iis.net/downloads/microsoft/url-rewrite 
  2. 創建一個地址重寫規則

image

image

image

這樣配置了之后,就不會再有ETag,整個世界清靜了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM