簡介
對于您的站點的訪問者來說涨缚,智能化的內(nèi)容緩存是提高用戶體驗最有效的方式之一。緩存,或者對之前的請求的臨時存儲脓魏,是HTTP協(xié)議實現(xiàn)中最核心的內(nèi)容分發(fā)策略之一兰吟。分發(fā)路徑中的組件均可以緩存內(nèi)容來加速后續(xù)的請求,這受控于對該內(nèi)容所聲明的緩存策略茂翔。
在這份指南中混蔼,我們將討論一些Web內(nèi)容緩存的基本概念。這主要包括如何選擇緩存策略以保證互聯(lián)網(wǎng)范圍內(nèi)的緩存能夠正確的處理您的內(nèi)容珊燎。我們將談一談緩存帶來的好處惭嚣、副作用以及不同的策略能帶來的性能和靈活性的最大結(jié)合。
什么是緩存(caching)悔政?
緩存(caching)是一個描述存儲可重用資源以便加快后續(xù)請求的行為的術(shù)語晚吞。有許多不同類型的緩存,每種都有其自身的特點谋国,應(yīng)用程序緩存和內(nèi)存緩存由于其對特定回復(fù)的加速槽地,都很常用。
這份指南的主要講述的Web緩存是一種不同類型的緩存芦瘾。Web緩存是HTTP協(xié)議的一個核心特性捌蚊,它能最小化網(wǎng)絡(luò)流量,并且提升用戶所感知的整個系統(tǒng)響應(yīng)速度近弟。內(nèi)容從服務(wù)器到瀏覽器的傳輸過程中缅糟,每個層面都可以找到緩存的身影。
Web緩存根據(jù)特定的規(guī)則緩存相應(yīng)HTTP請求的響應(yīng)祷愉。對于緩存內(nèi)容的后續(xù)請求便可以直接由緩存滿足而不是重新發(fā)送請求到Web服務(wù)器窗宦。
好處
有效的緩存技術(shù)不僅可以幫助用戶,還可以幫助內(nèi)容的提供者谣辞。緩存對內(nèi)容分發(fā)帶來的好處有:
- 減少網(wǎng)絡(luò)開銷:內(nèi)容可以在從內(nèi)容提供者到內(nèi)容消費者網(wǎng)絡(luò)路徑之間的許多不同的地方被緩存迫摔。當(dāng)內(nèi)容在距離內(nèi)容消費者更近的地方被緩存時沐扳,由于緩存的存在泥从,請求將不會消耗額外的網(wǎng)絡(luò)資源。
- 加快響應(yīng)速度:由于并不是必須通過整個網(wǎng)絡(luò)往返沪摄,緩存可以使內(nèi)容的獲得變得更快躯嫉。緩存放在距用戶更近的地方,例如瀏覽器緩存杨拐,使得內(nèi)容的獲取幾乎是瞬時的祈餐。
- 在同樣的硬件上提高速度:對于保存原始內(nèi)容的服務(wù)器來說,更多的性能可以通過允許激進的緩存策略從硬件上壓榨出來哄陶。內(nèi)容擁有者們可以利用分發(fā)路徑上某個強大的服務(wù)器來應(yīng)對特定內(nèi)容負載的沖擊帆阳。
- 網(wǎng)絡(luò)中斷時內(nèi)容依舊可用:使用某種策略,緩存可以保證在原始服務(wù)器變得不可用時屋吨,相應(yīng)的內(nèi)容對用戶依舊可用蜒谤。
術(shù)語
在面對緩存時山宾,您可能對一些經(jīng)常遇到的術(shù)語可能不太熟悉。一些常見的術(shù)語如下:
- 原始服務(wù)器:原始服務(wù)器是內(nèi)容的原始存放地點鳍徽。如果您是Web服務(wù)器管理員资锰,它就是您所管理的機器。它負責(zé)為任何不能從緩存中得到的內(nèi)容進行回復(fù)阶祭,并且負責(zé)設(shè)置所有內(nèi)容的緩存策略绷杜。
- 緩存命中率:一個緩存的有效性依照緩存的命中率進行度量。它是可以從緩存中得到數(shù)據(jù)的請求數(shù)與所有請求數(shù)的比率濒募。緩存命中率高意味著有很高比例的數(shù)據(jù)可以從緩存中獲得鞭盟。這通常是大多數(shù)管理員想要的結(jié)果埃撵。
- 新鮮度:新鮮度用來描述一個緩存中的項目是否依舊適合返回給客戶端奈懒。緩存中的內(nèi)容只有在由緩存策略指定的新鮮期內(nèi)才會被返回盔几。
- 過期內(nèi)容:緩存中根據(jù)緩存策略的新鮮期設(shè)置已過期的內(nèi)容损话。過期的內(nèi)容被標(biāo)記為“陳舊”戚绕。通常蜂奸,過期內(nèi)容不能用于回復(fù)客戶端的請求意推。必須重新從原始服務(wù)器請求新的內(nèi)容或者至少驗證緩存的內(nèi)容是否仍然準(zhǔn)確驶兜。
- 校驗:緩存中的過期內(nèi)容可以驗證是否有效以便刷新過期時間舀凛。驗證過程包括聯(lián)系原始服務(wù)器以檢查緩存的數(shù)據(jù)是否依舊代表了最近的版本俊扳。
- 失效:失效是依據(jù)過期日期從緩存中移除內(nèi)容的過程。當(dāng)內(nèi)容在原始服務(wù)器上已被改變時就必須這樣做猛遍,緩存中過期的內(nèi)容會導(dǎo)致客戶端發(fā)生問題馋记。
還有許多其他的緩存術(shù)語,不過上面的這些應(yīng)該能幫助您開始懊烤。
什么能被緩存梯醒?
某些特定的內(nèi)容比其他內(nèi)容更容易被緩存。對大多數(shù)站點來說腌紧,一些適合緩存的內(nèi)容如下:
- Logo和商標(biāo)圖像
- 普通的不變化的圖像(例如茸习,導(dǎo)航圖標(biāo))
- CSS樣式表
- 普通的Javascript文件
- 可下載的內(nèi)容
- 媒體文件
這些文件更傾向于不經(jīng)常改變,所以長時間的對它們進行緩存能獲得好處壁肋。
一些項目在緩存中必須加以注意:
- HTML頁面
- 會替換改變的圖像
- 經(jīng)常修改的Javascript和CSS文件
- 需要有認證后的cookies才能訪問的內(nèi)容
一些內(nèi)容從來不應(yīng)該被緩存:
- 與敏感信息相關(guān)的資源(銀行數(shù)據(jù)号胚,等)
- 用戶相關(guān)且經(jīng)常更改的數(shù)據(jù)
除上面的通用規(guī)則外,通常您需要指定一些規(guī)則以便于更好地緩存不同種類的內(nèi)容浸遗。例如猫胁,如果登錄的用戶都看到的是同樣的網(wǎng)站視圖,就應(yīng)該在任何地方緩存這個頁面跛锌。如果登錄的用戶會在一段時間內(nèi)看到站點中用戶特定的視圖弃秆,您應(yīng)該讓用戶的瀏覽器緩存該數(shù)據(jù)而不應(yīng)讓任何中介節(jié)點緩存該視圖。
Web內(nèi)容緩存的位置
Web內(nèi)容會在整個分發(fā)路徑中的許多不同的位置被緩存:
- 瀏覽器緩存:Web瀏覽器自身會維護一個小型緩存。典型地菠赚,瀏覽器使用一種策略指示緩存最重要的內(nèi)容盼樟。這可能是用戶相關(guān)的內(nèi)容或可能會再次請求且下載代價較高。
- 中間緩存代理:任何在客戶端和您的基礎(chǔ)架構(gòu)之間的服務(wù)器都可以按期望緩存一些內(nèi)容锈至。這些緩存可能由ISP(網(wǎng)絡(luò)服務(wù)提供者)或者其他獨立組織提供晨缴。
- 反向緩存:您的服務(wù)器基礎(chǔ)架構(gòu)可以為后端的服務(wù)實現(xiàn)自己的緩存。如果實現(xiàn)了緩存峡捡,那么便可以在處理請求的位置返回相應(yīng)的內(nèi)容而不用每次請求都使用后端服務(wù)击碗。
上面的這些位置通常都可以根據(jù)它們自身的緩存策略和內(nèi)容源的緩存策略緩存一些相應(yīng)的內(nèi)容。
緩存頭部
緩存策略依賴于兩個不同的因素们拙。所緩存的實體本身需要決定是否應(yīng)該緩存可接受的內(nèi)容稍途。它可以只緩存部分可以緩存的內(nèi)容,但不能緩存超過限制的內(nèi)容砚婆。
緩存行為主要由緩存策略決定械拍,而緩存策略由內(nèi)容擁有者設(shè)置。這些策略主要通過特定的HTTP頭部來清晰地表達装盯。
經(jīng)過幾個不同HTTP協(xié)議的變化坷虑,出現(xiàn)了一些不同的針對緩存方面的頭部,它們的復(fù)雜度各不相同埂奈。下面列出了那些你也許應(yīng)該注意的:
-
Expires
:盡管使用范圍相當(dāng)有限迄损,但Expires
頭部是非常簡潔明了的。通常它設(shè)置一個未來的時間账磺,內(nèi)容會在此時間過期芹敌。這時,任何對同樣內(nèi)容的請求都應(yīng)該回到原始服務(wù)器處垮抗。這個頭部或許僅僅最適合回退模式(fall back)氏捞。 -
Cache-Control
:這是Expires
的一個更加現(xiàn)代化的替換物。它已被很好的支持冒版,且擁有更加靈活的實現(xiàn)液茎。在大多數(shù)案例中,它比Expires
更好壤玫,但同時設(shè)置兩者的值也無妨豁护。稍后我們將討論您可以設(shè)置的Cache-Control
的詳細選項哼凯。 -
ETag
:ETag
用于緩存驗證欲间。源服務(wù)器可以在首次服務(wù)一個內(nèi)容時為該內(nèi)容提供一個獨特的ETag
。當(dāng)一個緩存需要驗證這個內(nèi)容是否即將過期断部,他會將相應(yīng)的ETag
發(fā)送回服務(wù)器猎贴。源服務(wù)器或者告訴緩存內(nèi)容是一致的,或者發(fā)送更新后的內(nèi)容(帶著新的ETag
)。 -
Last-Modified
:這個頭部指明了相應(yīng)的內(nèi)容最后一次被修改的時間她渴。它可能會作為保證內(nèi)容新鮮度的驗證策略的一部分被使用达址。 -
Content-Length
:盡管并沒有在緩存中明確涉及,Content-Length
頭部在設(shè)置緩存策略時很重要趁耗。某些軟件如果不提前獲知內(nèi)容的大小以留出足夠空間沉唠,則會拒絕緩存該內(nèi)容。 -
Vary
:緩存系統(tǒng)通常使用請求的主機和路徑作為存儲該資源的鍵苛败。當(dāng)判斷一個請求是否是請求同樣內(nèi)容時满葛,Vary
頭部可以被用來提醒緩存系統(tǒng)需要注意另一個附加頭部。它通常被用來告訴緩存系統(tǒng)同樣注意Accept-Encoding
頭部罢屈,以便緩存系統(tǒng)能夠區(qū)分壓縮和未壓縮的內(nèi)容嘀韧。
Vary頭部的隱語
Vary
頭部提供給您存儲同一個內(nèi)容的不同版本的能力,代價是降低了緩存的容量缠捌。
在使用Accept-Encoding
時锄贷,設(shè)置Vary
頭部允許明確區(qū)分壓縮和未壓縮的內(nèi)容。這在服務(wù)某些不能處理壓縮數(shù)據(jù)的瀏覽器時很重要曼月,它可以保證基本的可用性谊却。Vary
的一個典型的值是Accept-Encoding
,它只有兩到三個可選的值哑芹。
一開始看上去User-Agent
這樣的頭部可以用于區(qū)分移動瀏覽器和桌面瀏覽器因惭,以便您的站點提供差異化的服務(wù)。但User-Agent
字符串是非標(biāo)準(zhǔn)的绩衷,結(jié)果將會造成在中間緩存中保存同一內(nèi)容的許多不同版本的緩存蹦魔,這會導(dǎo)致緩存命中率的降低。Vary
頭部應(yīng)該謹慎使用咳燕,尤其是您不具備在您控制的中間緩存中使請求標(biāo)準(zhǔn)化的能力(也許可以勿决,比如您可以控制CDN的話)。
緩存控制標(biāo)志怎樣影響緩存
上面我們提到了Cache-Control
頭部如何被用與現(xiàn)代緩存策略標(biāo)準(zhǔn)招盲。能夠通過這個頭部設(shè)定許多不同的緩存指令低缩,多個不同的指令通過逗號分隔。
一些您可以使用的指示內(nèi)容緩存策略的Cache-Control
的選項如下:
-
no-cache
:這個指令指示所有緩存的內(nèi)容在新的請求到達時必須先重新驗證曹货,再發(fā)送給客戶端咆繁。這條指令實際將內(nèi)容立刻標(biāo)記為過期的,但允許通過驗證手段重新驗證以避免重新下載整個內(nèi)容顶籽。 -
no-store
:這條指令指示緩存的內(nèi)容不能以任何方式被緩存玩般。它適合在回復(fù)敏感信息時設(shè)置。 -
public
:它將內(nèi)容標(biāo)記為公有的礼饱,這意味著它能被瀏覽器和其他任何中間節(jié)點緩存坏为。通常究驴,對于使用了HTTP驗證的請求,其回復(fù)被默認標(biāo)記為private
匀伏。public
標(biāo)記將會覆蓋這個設(shè)置洒忧。 -
private
:它將內(nèi)容標(biāo)記為私有的。私有數(shù)據(jù)可以被用戶的瀏覽器緩存够颠,但不能被任何中間節(jié)點緩存熙侍。它通常用于用戶相關(guān)的數(shù)據(jù)。 -
max-age
:這個設(shè)置指示了緩存內(nèi)容的最大生存期履磨,它在最大生存期后必須在源服務(wù)器處被驗證或被重新下載核行。在現(xiàn)代瀏覽器中這個選項大體上取代了Expires
頭部,瀏覽器也將其作為決定內(nèi)容的新鮮度的基礎(chǔ)蹬耘。這個選項的值以秒為單位表示芝雪,最大可以表示一年的新鮮期(31536000秒)。 -
s-maxage
:這個選項非常類似于max-age
综苔,它指明了內(nèi)容能夠被緩存的時間惩系。區(qū)別是這個選項只在中間節(jié)點的緩存中有效。結(jié)合這兩個選項可以構(gòu)建更加靈活的緩存策略如筛。 -
must-revalidate
:它指明了由max-age
堡牡、s-maxage
或Expires
頭部指明的新鮮度信息必須被嚴格的遵守。它避免了緩存的數(shù)據(jù)在網(wǎng)絡(luò)中斷等類似的場景中被使用杨刨。 -
proxy-revalidate
:它和上面的選項有著一樣的作用晤柄,但只應(yīng)用于中間的代理節(jié)點。在這種情況下妖胀,用戶的瀏覽器可以在網(wǎng)絡(luò)中斷時使用過期內(nèi)容芥颈,但中間緩存內(nèi)容不能用于此目的。 -
no-transform
:這個選項告訴緩存在任何情況下都不能因為性能的原因修改接收到的內(nèi)容赚抡。這意味著爬坑,緩存不允許壓縮接收到的內(nèi)容(沒有從原始服務(wù)器處接收過壓縮版本的該內(nèi)容)并發(fā)送。
這些選項能夠以不同的方式結(jié)合以獲得不同的緩存行為涂臣。一些互斥的值如下:
-
no-cache
盾计,no-store
以及由其他前面未提到的選項指明的常用的緩存行為 -
public
和private
如果no-store
和no-cache
都被設(shè)置,那么no-store
會取代no-cache
赁遗。對于非授權(quán)的請求的回復(fù)署辉,public
是隱含的設(shè)置。對于授權(quán)的請求的回復(fù)岩四,private
選項是隱含的哭尝。他們可以通過在Cache-Control
頭部中指明相應(yīng)的相反的選項以覆蓋。
開發(fā)一種緩存策略
在理想情況下炫乓,任何內(nèi)容都可以被盡可能緩存刚夺,而您的服務(wù)器只需要偶爾的提供一些驗證內(nèi)容即可献丑。但這在現(xiàn)實中很少發(fā)生末捣,因此您應(yīng)該嘗試設(shè)置一些明智的緩存策略侠姑,以在長期緩存和站點改變的需求間達到平衡。
常見問題
在許多情況中箩做,由于內(nèi)容被產(chǎn)生的方式(如根據(jù)每個用戶動態(tài)的產(chǎn)生)或者內(nèi)容的特性(例如銀行的敏感數(shù)據(jù))莽红,這些內(nèi)容不應(yīng)該被緩存。另一些許多管理員在設(shè)置緩存時可能面對的問題是外部緩存的數(shù)據(jù)未過期邦邦,但新版本的數(shù)據(jù)已經(jīng)產(chǎn)生安吁。
這些都是經(jīng)常遇到的問題,它們會影響緩存的性能和您提供的數(shù)據(jù)的準(zhǔn)確性燃辖。然而鬼店,我們可以通過開發(fā)提前預(yù)見這些問題的緩存策略來緩解這些問題。
一般性建議
盡管您的實際情況會指導(dǎo)您選擇的緩存策略黔龟,但是下面的建議能幫助您獲得一些合理的決定妇智。
在您擔(dān)心使用哪一個特定的頭部之前,有一些特定的步驟可以幫助您提高您的緩存命中率氏身。一些建議如下:
- 為圖像巍棱、CSS和共享的內(nèi)容建立特定的文件夾:將內(nèi)容放到特定的文件夾內(nèi)使得您可以方便的從您的站點中的任何頁面引用這些內(nèi)容。
- 使用同樣的URL來表示同樣的內(nèi)容:由于緩存使用內(nèi)容請求中的主機名和路徑作為鍵蛋欣,因此應(yīng)保證您的所有頁面中的該內(nèi)容的引用方式相同航徙,前一個建議能讓這點更加容易做到。
- 盡可能使用CSS圖像拼接:對于像圖標(biāo)和導(dǎo)航等內(nèi)容陷虎,使用CSS圖像拼接能夠減少渲染您頁面所需要的請求往返到踏,并且允許對拼接緩存很長一段時間。
- 盡可能將主機腳本和外部資源本地化:如果您使用Javascript腳本和其他外部資源尚猿,如果上游沒有提供合適的緩存頭部夭禽,那么您應(yīng)考慮將這些內(nèi)容放在您自己的服務(wù)器上。您應(yīng)該注意上游的任何更新谊路,以便更新本地的拷貝讹躯。
- 對緩存內(nèi)容收集文件摘要:靜態(tài)的內(nèi)容比如CSS和Javascript文件等通常比較適合收集文件摘要。這意味著為文件名增加一個獨特的標(biāo)志符(通常是這個文件的哈希值)可以在文件修改后繞開緩存保證新的內(nèi)容被重新獲取缠劝。有很多工具可以幫助您創(chuàng)建文件摘要并且修改HTML文檔中的引用潮梯。
對于不同的文件正確地選擇不同的頭部這件事,下面的內(nèi)容可以作為一般性的參考:
- 允許所有的緩存存儲一般內(nèi)容:靜態(tài)內(nèi)容以及非用戶相關(guān)的內(nèi)容應(yīng)該在分發(fā)鏈的所有節(jié)點被緩存惨恭。這使得中間節(jié)點可以將該內(nèi)容回復(fù)給多個用戶秉馏。
- 允許瀏覽器緩存用戶相關(guān)的內(nèi)容:對于每個用戶的數(shù)據(jù),通常在用戶自己的瀏覽器中緩存是可以被接受且有益的脱羡。緩存在用戶自身的瀏覽器能夠使得用戶在接下來的瀏覽中能夠瞬時讀取萝究,但這些內(nèi)容不適合在任何中間代理節(jié)點緩存免都。
-
將時間敏感的內(nèi)容作為特例:如果您的數(shù)據(jù)是時間敏感的,那么相對上面兩條參考帆竹,應(yīng)該將這些數(shù)據(jù)作為特例绕娘,以保證過期的數(shù)據(jù)不會在關(guān)鍵的情況下被使用。例如栽连,您的站點有一個購物車险领,它應(yīng)該立刻反應(yīng)購物車里面的物品。依據(jù)內(nèi)容的特點秒紧,可以在
Cache-Control
頭部中使用no-cache
或no-store
選項绢陌。 -
總是提供驗證器:驗證器使得過期的內(nèi)容可以無需重新下載而得到刷新。設(shè)置
ETag
和Last-Modified
頭部將允許緩存向原始服務(wù)器驗證內(nèi)容熔恢,并在內(nèi)容未修改時刷新該內(nèi)容新鮮度以減少負載脐湾。 - 對于支持的內(nèi)容設(shè)置長的新鮮期:為了更加有效的利用緩存,一些作為支持性的內(nèi)容應(yīng)該被設(shè)置較長的新鮮期叙淌。這通常比較適合圖像和CSS等由用戶請求用來渲染HTML頁面的內(nèi)容秤掌。和文件摘要一起,設(shè)置延長的新鮮期將允許緩存長時間的存儲這些資源凿菩。如果資源發(fā)生改變机杜,修改的文件摘要將會使緩存的數(shù)據(jù)無效并觸發(fā)對新的內(nèi)容的下載。那時衅谷,新的支持的內(nèi)容會繼續(xù)被緩存椒拗。
- 對父內(nèi)容設(shè)置短的新鮮期:為了使得前面的模式正常工作,容器類的內(nèi)容應(yīng)該相應(yīng)的設(shè)置短的新鮮期获黔,或者設(shè)置不全部緩存蚀苛。這通常是在其他協(xié)助內(nèi)容中使用的HTML頁面。這個HTML頁面將會被頻繁的下載玷氏,使得它能快速的響應(yīng)改變堵未。支持性的內(nèi)容因此可以被盡量緩存。
關(guān)鍵之處便在于達到平衡盏触,一方面可以盡量的進行緩存渗蟹,另一方面為未來保留當(dāng)改變發(fā)生時從而改變整個內(nèi)容的機會。您的站點應(yīng)該同時具有:
- 盡量緩存的內(nèi)容
- 擁有短的新鮮期的緩存內(nèi)容赞辩,可以被重新驗證
- 完全不被緩存的內(nèi)容
這樣做的目的便是將內(nèi)容盡可能的移動到第一個分類(盡量緩存)中的同時雌芽,維持可以接受的緩存命中率。
結(jié)論
花時間確保您的站點使用了合適的緩存策略將對您的站點產(chǎn)生重要的影響辨嗽。緩存使得您可以在保證服務(wù)同樣內(nèi)容的同時減少帶寬的使用世落。您的服務(wù)器因此可以靠同樣的硬件處理更多的流量≡阈瑁或許更重要的是屉佳,客戶們能在您的網(wǎng)站中獲得更快的體驗谷朝,這會使得他們更愿意頻繁的訪問您的站點。盡管有效的Web緩存并不是銀彈武花,但設(shè)置合適的緩存策略會使您以最小的代價獲得可觀的收獲圆凰。
作者: Justin Ellingwood
譯者:wwy-hust
校對:wxy
推薦:royaso