對於您的站點的訪問者來講,智能化的內容緩存是提升用戶體驗最有效的方式之一。緩存,或者對以前的請求的臨時存儲,是HTTP協議實現中最核心的內容分發策略之一。分發路徑中的組件都可以緩存內容來加速後續的請求,這受控於對該內容所聲明的緩存策略。後端
在這份指南中,咱們將討論一些Web內容緩存的基本概念。這主要包括如何選擇緩存策略以保證互聯網範圍內的緩存可以正確的處理您的內容。咱們將談一談緩存帶來的好處、反作用以及不一樣的策略能帶來的性能和靈活性的最大結合。瀏覽器
緩存(caching)是一個描述存儲可重用資源以便加快後續請求的行爲的術語。有許多不一樣類型的緩存,每種都有其自身的特色,應用程序緩存和內存緩存因爲其對特定回覆的加速,都很經常使用。緩存
這份指南的主要講述的Web緩存是一種不一樣類型的緩存。Web緩存是HTTP協議的一個核心特性,它能最小化網絡流量,而且提高用戶所感知的整個系統響應速度。內容從服務器到瀏覽器的傳輸過程當中,每一個層面均可以找到緩存的身影。服務器
Web緩存根據特定的規則緩存相應HTTP請求的響應。對於緩存內容的後續請求即可以直接由緩存知足而不是從新發送請求到Web服務器。cookie
有效的緩存技術不只能夠幫助用戶,還能夠幫助內容的提供者。緩存對內容分發帶來的好處有:網絡
在面對緩存時,您可能對一些常常遇到的術語可能不太熟悉。一些常見的術語以下:架構
還有許多其餘的緩存術語,不過上面的這些應該能幫助您開始。併發
某些特定的內容比其餘內容更容易被緩存。對大多數站點來講,一些適合緩存的內容以下:工具
這些文件更傾向於不常常改變,因此長時間的對它們進行緩存能得到好處。性能
一些項目在緩存中必須加以注意:
一些內容歷來不該該被緩存:
除上面的通用規則外,一般您須要指定一些規則以便於更好地緩存不一樣種類的內容。例如,若是登陸的用戶都看到的是一樣的網站視圖,就應該在任何地方緩存這個頁面。若是登陸的用戶會在一段時間內看到站點中用戶特定的視圖,您應該讓用戶的瀏覽器緩存該數據而不該讓任何中介節點緩存該視圖。
Web內容會在整個分發路徑中的許多不一樣的位置被緩存:
上面的這些位置一般均可以根據它們自身的緩存策略和內容源的緩存策略緩存一些相應的內容。
緩存策略依賴於兩個不一樣的因素。所緩存的實體自己須要決定是否應該緩存可接受的內容。它能夠只緩存部分能夠緩存的內容,但不能緩存超過限制的內容。
緩存行爲主要由緩存策略決定,而緩存策略由內容擁有者設置。這些策略主要經過特定的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
頭部提供給您存儲同一個內容的不一樣版本的能力,代價是下降了緩存的容量。
在使用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
頭部中指明相應的相反的選項以覆蓋。
在理想狀況下,任何內容均可以被儘量緩存,而您的服務器只須要偶爾的提供一些驗證內容便可。但這在現實中不多發生,所以您應該嘗試設置一些明智的緩存策略,以在長期緩存和站點改變的需求間達到平衡。
在許多狀況中,因爲內容被產生的方式(如根據每一個用戶動態的產生)或者內容的特性(例如銀行的敏感數據),這些內容不該該被緩存。另外一些許多管理員在設置緩存時可能面對的問題是外部緩存的數據未過時,但新版本的數據已經產生。
這些都是常常遇到的問題,它們會影響緩存的性能和您提供的數據的準確性。然而,咱們能夠經過開發提早預見這些問題的緩存策略來緩解這些問題。
儘管您的實際狀況會指導您選擇的緩存策略,可是下面的建議能幫助您得到一些合理的決定。
在您擔憂使用哪個特定的頭部以前,有一些特定的步驟能夠幫助您提升您的緩存命中率。一些建議以下:
對於不一樣的文件正確地選擇不一樣的頭部這件事,下面的內容能夠做爲通常性的參考:
Cache-Control
頭部中使用no-cache
或no-store
選項。ETag
和Last-Modified
頭部將容許緩存向原始服務器驗證內容,並在內容未修改時刷新該內容新鮮度以減小負載。關鍵之處便在於達到平衡,一方面能夠儘可能的進行緩存,另外一方面爲將來保留當改變發生時從而改變整個內容的機會。您的站點應該同時具備:
這樣作的目的即是將內容儘量的移動到第一個分類(儘可能緩存)中的同時,維持能夠接受的緩存命中率。