Web緩存基礎:術語、HTTP報頭和緩存策略

簡介

對於您的站點的訪問者來講,智能化的內容緩存是提升用戶體驗最有效的方式之一。緩存,或者對以前的請求的臨時存儲,是HTTP協議實現中最核心的內容分發策略之一。分發路徑中的組件都可以緩存內容來加速後續的請求,這受控於對該內容所聲明的緩存策略。後端

在這份指南中,咱們將討論一些Web內容緩存的基本概念。這主要包括如何選擇緩存策略以保證互聯網範圍內的緩存可以正確的處理您的內容。咱們將談一談緩存帶來的好處、反作用以及不一樣的策略能帶來的性能和靈活性的最大結合。瀏覽器

什麼是緩存(caching)?

緩存(caching)是一個描述存儲可重用資源以便加快後續請求的行爲的術語。有許多不一樣類型的緩存,每種都有其自身的特色,應用程序緩存和內存緩存因爲其對特定回覆的加速,都很經常使用。緩存

這份指南的主要講述的Web緩存是一種不一樣類型的緩存。Web緩存是HTTP協議的一個核心特性,它能最小化網絡流量,而且提高用戶所感知的整個系統響應速度。內容從服務器到瀏覽器的傳輸過程當中,每一個層面均可以找到緩存的身影。服務器

Web緩存根據特定的規則緩存相應HTTP請求的響應。對於緩存內容的後續請求即可以直接由緩存知足而不是從新發送請求到Web服務器。cookie

好處

有效的緩存技術不只能夠幫助用戶,還能夠幫助內容的提供者。緩存對內容分發帶來的好處有:網絡

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

術語

在面對緩存時,您可能對一些常常遇到的術語可能不太熟悉。一些常見的術語以下:架構

  • 原始服務器:原始服務器是內容的原始存放地點。若是您是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驗證的請求,其回覆被默認標記爲privatepublic標記將會覆蓋這個設置。
  • private:它將內容標記爲私有的。私有數據能夠被用戶的瀏覽器緩存,但不能被任何中間節點緩存。它一般用於用戶相關的數據。
  • max-age:這個設置指示了緩存內容的最大生存期,它在最大生存期後必須在源服務器處被驗證或被從新下載。在現代瀏覽器中這個選項大致上取代了Expires頭部,瀏覽器也將其做爲決定內容的新鮮度的基礎。這個選項的值以秒爲單位表示,最大能夠表示一年的新鮮期(31536000秒)。
  • s-maxage:這個選項很是相似於max-age,它指明瞭內容可以被緩存的時間。區別是這個選項只在中間節點的緩存中有效。結合這兩個選項能夠構建更加靈活的緩存策略。
  • must-revalidate:它指明瞭由max-ages-maxageExpires頭部指明的新鮮度信息必須被嚴格的遵照。它避免了緩存的數據在網絡中斷等相似的場景中被使用。
  • proxy-revalidate:它和上面的選項有着同樣的做用,但只應用於中間的代理節點。在這種狀況下,用戶的瀏覽器能夠在網絡中斷時使用過時內容,但中間緩存內容不能用於此目的。
  • no-transform:這個選項告訴緩存在任何狀況下都不能由於性能的緣由修改接收到的內容。這意味着,緩存不容許壓縮接收到的內容(沒有從原始服務器處接收過壓縮版本的該內容)併發送。

這些選項可以以不一樣的方式結合以得到不一樣的緩存行爲。一些互斥的值以下:

  • no-cacheno-store以及由其餘前面未提到的選項指明的經常使用的緩存行爲
  • publicprivate

若是no-storeno-cache都被設置,那麼no-store會取代no-cache。對於非受權的請求的回覆,public是隱含的設置。對於受權的請求的回覆,private選項是隱含的。他們能夠經過在Cache-Control頭部中指明相應的相反的選項以覆蓋。

開發一種緩存策略

在理想狀況下,任何內容均可以被儘量緩存,而您的服務器只須要偶爾的提供一些驗證內容便可。但這在現實中不多發生,所以您應該嘗試設置一些明智的緩存策略,以在長期緩存和站點改變的需求間達到平衡。

常見問題

在許多狀況中,因爲內容被產生的方式(如根據每一個用戶動態的產生)或者內容的特性(例如銀行的敏感數據),這些內容不該該被緩存。另外一些許多管理員在設置緩存時可能面對的問題是外部緩存的數據未過時,但新版本的數據已經產生。

這些都是常常遇到的問題,它們會影響緩存的性能和您提供的數據的準確性。然而,咱們能夠經過開發提早預見這些問題的緩存策略來緩解這些問題。

通常性建議

儘管您的實際狀況會指導您選擇的緩存策略,可是下面的建議能幫助您得到一些合理的決定。

在您擔憂使用哪個特定的頭部以前,有一些特定的步驟能夠幫助您提升您的緩存命中率。一些建議以下:

  • 爲圖像、CSS和共享的內容創建特定的文件夾:將內容放到特定的文件夾內使得您能夠方便的從您的站點中的任何頁面引用這些內容。
  • 使用一樣的URL來表示一樣的內容:因爲緩存使用內容請求中的主機名和路徑做爲鍵,所以應保證您的全部頁面中的該內容的引用方式相同,前一個建議能讓這點更加容易作到。
  • 儘量使用CSS圖像拼接:對於像圖標和導航等內容,使用CSS圖像拼接可以減小渲染您頁面所須要的請求往返,而且容許對拼接緩存很長一段時間。
  • 儘量將主機腳本和外部資源本地化:若是您使用Javascript腳本和其餘外部資源,若是上游沒有提供合適的緩存頭部,那麼您應考慮將這些內容放在您本身的服務器上。您應該注意上游的任何更新,以便更新本地的拷貝。
  • 對緩存內容收集文件摘要:靜態的內容好比CSS和Javascript文件等一般比較適合收集文件摘要。這意味着爲文件名增長一個獨特的標誌符(一般是這個文件的哈希值)能夠在文件修改後繞開緩存保證新的內容被從新獲取。有不少工具能夠幫助您建立文件摘要而且修改HTML文檔中的引用。

對於不一樣的文件正確地選擇不一樣的頭部這件事,下面的內容能夠做爲通常性的參考:

  • 容許全部的緩存存儲通常內容:靜態內容以及非用戶相關的內容應該在分發鏈的全部節點被緩存。這使得中間節點能夠將該內容回覆給多個用戶。
  • 容許瀏覽器緩存用戶相關的內容:對於每一個用戶的數據,一般在用戶本身的瀏覽器中緩存是能夠被接受且有益的。緩存在用戶自身的瀏覽器可以使得用戶在接下來的瀏覽中可以瞬時讀取,但這些內容不適合在任何中間代理節點緩存。
  • 將時間敏感的內容做爲特例:若是您的數據是時間敏感的,那麼相對上面兩條參考,應該將這些數據做爲特例,以保證過時的數據不會在關鍵的狀況下被使用。例如,您的站點有一個購物車,它應該馬上反應購物車裏面的物品。依據內容的特色,能夠在Cache-Control頭部中使用no-cacheno-store選項。
  • 老是提供驗證器:驗證器使得過時的內容能夠無需從新下載而獲得刷新。設置ETagLast-Modified頭部將容許緩存向原始服務器驗證內容,並在內容未修改時刷新該內容新鮮度以減小負載。
  • 對於支持的內容設置長的新鮮期:爲了更加有效的利用緩存,一些做爲支持性的內容應該被設置較長的新鮮期。這一般比較適合圖像和CSS等由用戶請求用來渲染HTML頁面的內容。和文件摘要一塊兒,設置延長的新鮮期將容許緩存長時間的存儲這些資源。若是資源發生改變,修改的文件摘要將會使緩存的數據無效並觸發對新的內容的下載。那時,新的支持的內容會繼續被緩存。
  • 對父內容設置短的新鮮期:爲了使得前面的模式正常工做,容器類的內容應該相應的設置短的新鮮期,或者設置不所有緩存。這一般是在其餘協助內容中使用的HTML頁面。這個HTML頁面將會被頻繁的下載,使得它能快速的響應改變。支持性的內容所以能夠被儘可能緩存。

關鍵之處便在於達到平衡,一方面能夠儘可能的進行緩存,另外一方面爲將來保留當改變發生時從而改變整個內容的機會。您的站點應該同時具備:

  • 儘可能緩存的內容
  • 擁有短的新鮮期的緩存內容,能夠被從新驗證
  • 徹底不被緩存的內容

這樣作的目的即是將內容儘量的移動到第一個分類(儘可能緩存)中的同時,維持能夠接受的緩存命中率。

相關文章
相關標籤/搜索