Web快取基礎:術語、HTTP報頭和快取策略

linux.cn發表於2015-05-17

簡介

對於您的站點的訪問者來說,智慧化的內容快取是提高使用者體驗最有效的方式之一。快取,或者對之前的請求的臨時儲存,是HTTP協議實現中最核心的內容分發策略之一。分發路徑中的元件均可以快取內容來加速後續的請求,這受控於對該內容所宣告的快取策略。

在這份指南中,我們將討論一些Web內容快取的基本概念。這主要包括如何選擇快取策略以保證網際網路範圍內的快取能夠正確的處理您的內容。我們將談一談快取帶來的好處、副作用以及不同的策略能帶來的效能和靈活性的最大結合。

Web快取基礎:術語、HTTP報頭和快取策略

什麼是快取(caching)?

快取(caching)是一個描述儲存可重用資源以便加快後續請求的行為的術語。有許多不同型別的快取,每種都有其自身的特點,應用程式快取和記憶體快取由於其對特定回覆的加速,都很常用。

這份指南的主要講述的Web快取是一種不同型別的快取。Web快取是HTTP協議的一個核心特性,它能最小化網路流量,並且提升使用者所感知的整個系統響應速度。內容從伺服器到瀏覽器的傳輸過程中,每個層面都可以找到快取的身影。

Web快取根據特定的規則快取相應HTTP請求的響應。對於快取內容的後續請求便可以直接由快取滿足而不是重新傳送請求到Web伺服器。

好處

有效的快取技術不僅可以幫助使用者,還可以幫助內容的提供者。快取對內容分發帶來的好處有:

  • 減少網路開銷:內容可以在從內容提供者到內容消費者網路路徑之間的許多不同的地方被快取。當內容在距離內容消費者更近的地方被快取時,由於快取的存在,請求將不會消耗額外的網路資源。
  • 加快響應速度:由於並不是必須通過整個網路往返,快取可以使內容的獲得變得更快。快取放在距使用者更近的地方,例如瀏覽器快取,使得內容的獲取幾乎是瞬時的。
  • 在同樣的硬體上提高速度:對於儲存原始內容的伺服器來說,更多的效能可以通過允許激進的快取策略從硬體上壓榨出來。內容擁有者們可以利用分發路徑上某個強大的伺服器來應對特定內容負載的衝擊。
  • 網路中斷時內容依舊可用:使用某種策略,快取可以保證在原始伺服器變得不可用時,相應的內容對使用者依舊可用。

術語

在面對快取時,您可能對一些經常遇到的術語可能不太熟悉。一些常見的術語如下:

  • 原始伺服器:原始伺服器是內容的原始存放地點。如果您是Web伺服器管理員,它就是您所管理的機器。它負責為任何不能從快取中得到的內容進行回覆,並且負責設定所有內容的快取策略。
  • 快取命中率:一個快取的有效性依照快取的命中率進行度量。它是可以從快取中得到資料的請求數與所有請求數的比率。快取命中率高意味著有很高比例的資料可以從快取中獲得。這通常是大多數管理員想要的結果。
  • 新鮮度:新鮮度用來描述一個快取中的專案是否依舊適合返回給客戶端。快取中的內容只有在由快取策略指定的新鮮期內才會被返回。
  • 過期內容:快取中根據快取策略的新鮮期設定已過期的內容。過期的內容被標記為“陳舊”。通常,過期內容不能用於回覆客戶端的請求。必須重新從原始伺服器請求新的內容或者至少驗證快取的內容是否仍然準確。
  • 校驗:快取中的過期內容可以驗證是否有效以便重新整理過期時間。驗證過程包括聯絡原始伺服器以檢查快取的資料是否依舊代表了最近的版本。
  • 失效:失效是依據過期日期從快取中移除內容的過程。當內容在原始伺服器上已被改變時就必須這樣做,快取中過期的內容會導致客戶端發生問題。

還有許多其他的快取術語,不過上面的這些應該能幫助您開始。

什麼能被快取?

某些特定的內容比其他內容更容易被快取。對大多數站點來說,一些適合快取的內容如下:

  • Logo和商標影像
  • 普通的不變化的影像(例如,導航圖示)
  • CSS樣式表
  • 普通的Javascript檔案
  • 可下載的內容
  • 媒體檔案

這些檔案更傾向於不經常改變,所以長時間的對它們進行快取能獲得好處。

一些專案在快取中必須加以注意:

  • HTML頁面
  • 會替換改變的影像
  • 經常修改的Javascript和CSS檔案
  • 需要有認證後的cookies才能訪問的內容

一些內容從來不應該被快取:

  • 與敏感資訊相關的資源(銀行資料,等)
  • 使用者相關且經常更改的資料

除上面的通用規則外,通常您需要指定一些規則以便於更好地快取不同種類的內容。例如,如果登入的使用者都看到的是同樣的網站檢視,就應該在任何地方快取這個頁面。如果登入的使用者會在一段時間內看到站點中使用者特定的檢視,您應該讓使用者的瀏覽器快取該資料而不應讓任何中介節點快取該檢視。

Web內容快取的位置

Web內容會在整個分發路徑中的許多不同的位置被快取:

  • 瀏覽器快取:Web瀏覽器自身會維護一個小型快取。典型地,瀏覽器使用一種策略指示快取最重要的內容。這可能是使用者相關的內容或可能會再次請求且下載代價較高。
  • 中間快取代理:任何在客戶端和您的基礎架構之間的伺服器都可以按期望快取一些內容。這些快取可能由ISP(網路服務提供者)或者其他獨立組織提供。
  • 反向快取:您的伺服器基礎架構可以為後端的服務實現自己的快取。如果實現了快取,那麼便可以在處理請求的位置返回相應的內容而不用每次請求都使用後端服務。

上面的這些位置通常都可以根據它們自身的快取策略和內容源的快取策略快取一些相應的內容。

快取頭部

快取策略依賴於兩個不同的因素。所快取的實體本身需要決定是否應該快取可接受的內容。它可以只快取部分可以快取的內容,但不能快取超過限制的內容。

快取行為主要由快取策略決定,而快取策略由內容擁有者設定。這些策略主要通過特定的HTTP頭部來清晰地表達。

經過幾個不同HTTP協議的變化,出現了一些不同的針對快取方面的頭部,它們的複雜度各不相同。下面列出了那些你也許應該注意的:

  • **Expires**:儘管使用範圍相當有限,但Expires頭部是非常簡潔明瞭的。通常它設定一個未來的時間,內容會在此時間過期。這時,任何對同樣內容的請求都應該回到原始伺服器處。這個頭部或許僅僅最適合回退模式(fall back)。
  • **Cache-Control**:這是Expires的一個更加現代化的替換物。它已被很好的支援,且擁有更加靈活的實現。在大多數案例中,它比Expires更好,但同時設定兩者的值也無妨。稍後我們將討論您可以設定的Cache-Control的詳細選項。
  • **ETag**:ETag用於快取驗證。源伺服器可以在首次服務一個內容時為該內容提供一個獨特的ETag。當一個快取需要驗證這個內容是否即將過期,他會將相應的ETag傳送回伺服器。源伺服器或者告訴快取內容是一致的,或者傳送更新後的內容(帶著新的ETag)。
  • Last-Modified:這個頭部指明瞭相應的內容最後一次被修改的時間。它可能會作為保證內容新鮮度的驗證策略的一部分被使用。
  • **Content-Length**:儘管並沒有在快取中明確涉及,Content-Length頭部在設定快取策略時很重要。某些軟體如果不提前獲知內容的大小以留出足夠空間,則會拒絕快取該內容。
  • **Vary**:快取系統通常使用請求的主機和路徑作為儲存該資源的鍵。當判斷一個請求是否是請求同樣內容時,Vary頭部可以被用來提醒快取系統需要注意另一個附加頭部。它通常被用來告訴快取系統同樣注意Accept-Encoding頭部,以便快取系統能夠區分壓縮和未壓縮的內容。

Vary頭部的隱語

Vary頭部提供給您儲存同一個內容的不同版本的能力,代價是降低了快取的容量。

在使用Accept-Encoding時,設定Vary頭部允許明確區分壓縮和未壓縮的內容。這在服務某些不能處理壓縮資料的瀏覽器時很重要,它可以保證基本的可用性。Vary的一個典型的值是Accept-Encoding,它只有兩到三個可選的值。

一開始看上去User-Agent這樣的頭部可以用於區分移動瀏覽器和桌面瀏覽器,以便您的站點提供差異化的服務。但User-Agent字串是非標準的,結果將會造成在中間快取中儲存同一內容的許多不同版本的快取,這會導致快取命中率的降低。Vary頭部應該謹慎使用,尤其是您不具備在您控制的中間快取中使請求標準化的能力(也許可以,比如您可以控制CDN的話)。

快取控制標誌怎樣影響快取

上面我們提到了Cache-Control頭部如何被用與現代快取策略標準。能夠通過這個頭部設定許多不同的快取指令,多個不同的指令通過逗號分隔。

一些您可以使用的指示內容快取策略的Cache-Control的選項如下:

  • no-cache:這個指令指示所有快取的內容在新的請求到達時必須先重新驗證,再傳送給客戶端。這條指令實際將內容立刻標記為過期的,但允許通過驗證手段重新驗證以避免重新下載整個內容。
  • no-store:這條指令指示快取的內容不能以任何方式被快取。它適合在回覆敏感資訊時設定。
  • public:它將內容標記為公有的,這意味著它能被瀏覽器和其他任何中間節點快取。通常,對於使用了HTTP驗證的請求,其回覆被預設標記為private。public標記將會覆蓋這個設定。
  • private:它將內容標記為私有的。私有資料可以被使用者的瀏覽器快取,但不能被任何中間節點快取。它通常用於使用者相關的資料。
  • max-age:這個設定指示了快取內容的最大生存期,它在最大生存期後必須在源伺服器處被驗證或被重新下載。在現代瀏覽器中這個選項大體上取代了Expires頭部,瀏覽器也將其作為決定內容的新鮮度的基礎。這個選項的值以秒為單位表示,最大可以表示一年的新鮮期(31536000秒)。
  • s-maxage:這個選項非常類似於max-age,它指明瞭內容能夠被快取的時間。區別是這個選項只在中間節點的快取中有效。結合這兩個選項可以構建更加靈活的快取策略。
  • must-revalidate:它指明瞭由max-age、s-maxage或Expires頭部指明的新鮮度資訊必須被嚴格的遵守。它避免了快取的資料在網路中斷等類似的場景中被使用。
  • proxy-revalidate:它和上面的選項有著一樣的作用,但只應用於中間的代理節點。在這種情況下,使用者的瀏覽器可以在網路中斷時使用過期內容,但中間快取內容不能用於此目的。
  • no-transform:這個選項告訴快取在任何情況下都不能因為效能的原因修改接收到的內容。這意味著,快取不允許壓縮接收到的內容(沒有從原始伺服器處接收過壓縮版本的該內容)併傳送。

這些選項能夠以不同的方式結合以獲得不同的快取行為。一些互斥的值如下:

  • no-cache,no-store以及由其他前面未提到的選項指明的常用的快取行為
  • public和private

如果no-store和no-cache都被設定,那麼no-store會取代no-cache。對於非授權的請求的回覆,public是隱含的設定。對於授權的請求的回覆,private選項是隱含的。他們可以通過在Cache-Control頭部中指明相應的相反的選項以覆蓋。

開發一種快取策略

在理想情況下,任何內容都可以被儘可能快取,而您的伺服器只需要偶爾的提供一些驗證內容即可。但這在現實中很少發生,因此您應該嘗試設定一些明智的快取策略,以在長期快取和站點改變的需求間達到平衡。

常見問題

在許多情況中,由於內容被產生的方式(如根據每個使用者動態的產生)或者內容的特性(例如銀行的敏感資料),這些內容不應該被快取。另一些許多管理員在設定快取時可能面對的問題是外部快取的資料未過期,但新版本的資料已經產生。

這些都是經常遇到的問題,它們會影響快取的效能和您提供的資料的準確性。然而,我們可以通過開發提前預見這些問題的快取策略來緩解這些問題。

一般性建議

儘管您的實際情況會指導您選擇的快取策略,但是下面的建議能幫助您獲得一些合理的決定。

在您擔心使用哪一個特定的頭部之前,有一些特定的步驟可以幫助您提高您的快取命中率。一些建議如下:

  • 為影像、CSS和共享的內容建立特定的資料夾:將內容放到特定的資料夾內使得您可以方便的從您的站點中的任何頁面引用這些內容。
  • 使用同樣的URL來表示同樣的內容:由於快取使用內容請求中的主機名和路徑作為鍵,因此應保證您的所有頁面中的該內容的引用方式相同,前一個建議能讓這點更加容易做到。
  • 儘可能使用CSS影像拼接:對於像圖示和導航等內容,使用CSS影像拼接能夠減少渲染您頁面所需要的請求往返,並且允許對拼接快取很長一段時間。
  • 儘可能將主機指令碼和外部資源本地化:如果您使用Javascript指令碼和其他外部資源,如果上游沒有提供合適的快取頭部,那麼您應考慮將這些內容放在您自己的伺服器上。您應該注意上游的任何更新,以便更新本地的拷貝。
  • 對快取內容收集檔案摘要:靜態的內容比如CSS和Javascript檔案等通常比較適合收集檔案摘要。這意味著為檔名增加一個獨特的標誌符(通常是這個檔案的雜湊值)可以在檔案修改後繞開快取保證新的內容被重新獲取。有很多工具可以幫助您建立檔案摘要並且修改HTML文件中的引用。

對於不同的檔案正確地選擇不同的頭部這件事,下面的內容可以作為一般性的參考:

  • 允許所有的快取儲存一般內容:靜態內容以及非使用者相關的內容應該在分發鏈的所有節點被快取。這使得中間節點可以將該內容回覆給多個使用者。
  • 允許瀏覽器快取使用者相關的內容:對於每個使用者的資料,通常在使用者自己的瀏覽器中快取是可以被接受且有益的。快取在使用者自身的瀏覽器能夠使得使用者在接下來的瀏覽中能夠瞬時讀取,但這些內容不適合在任何中間代理節點快取。
  • 將時間敏感的內容作為特例:如果您的資料是時間敏感的,那麼相對上面兩條參考,應該將這些資料作為特例,以保證過期的資料不會在關鍵的情況下被使用。例如,您的站點有一個購物車,它應該立刻反應購物車裡面的物品。依據內容的特點,可以在Cache-Control頭部中使用no-cache或no-store選項。
  • 總是提供驗證器:驗證器使得過期的內容可以無需重新下載而得到重新整理。設定ETag和Last-Modified頭部將允許快取向原始伺服器驗證內容,並在內容未修改時重新整理該內容新鮮度以減少負載。
  • 對於支援的內容設定長的新鮮期:為了更加有效的利用快取,一些作為支援性的內容應該被設定較長的新鮮期。這通常比較適合影像和CSS等由使用者請求用來渲染HTML頁面的內容。和檔案摘要一起,設定延長的新鮮期將允許快取長時間的儲存這些資源。如果資源發生改變,修改的檔案摘要將會使快取的資料無效並觸發對新的內容的下載。那時,新的支援的內容會繼續被快取。
  • 對父內容設定短的新鮮期:為了使得前面的模式正常工作,容器類的內容應該相應的設定短的新鮮期,或者設定不全部快取。這通常是在其他協助內容中使用的HTML頁面。這個HTML頁面將會被頻繁的下載,使得它能快速的響應改變。支援性的內容因此可以被儘量快取。

關鍵之處便在於達到平衡,一方面可以儘量的進行快取,另一方面為未來保留當改變發生時從而改變整個內容的機會。您的站點應該同時具有:

  • 儘量快取的內容
  • 擁有短的新鮮期的快取內容,可以被重新驗證
  • 完全不被快取的內容

這樣做的目的便是將內容儘可能的移動到第一個分類(儘量快取)中的同時,維持可以接受的快取命中率。

結論

花時間確保您的站點使用了合適的快取策略將對您的站點產生重要的影響。快取使得您可以在保證服務同樣內容的同時減少頻寬的使用。您的伺服器因此可以靠同樣的硬體處理更多的流量。或許更重要的是,客戶們能在您的網站中獲得更快的體驗,這會使得他們更願意頻繁的訪問您的站點。儘管有效的Web快取並不是銀彈,但設定合適的快取策略會使您以最小的代價獲得可觀的收穫。

相關文章