前言
緩存對于Web開發有重要作用,尤其是大負荷Web系統開發中。
MDove:當然即使不是Web開發,緩存的意義也是舉足輕重。拿客戶端來說,從硬盤數據庫取肯定要比網絡獲取快,從內存取一定比從硬盤數據庫取更快。雖說HTTP緩存在客戶端上的場景并不多見,但是其思想是相通的,學習一波總歸沒有壞處。
所以今天讓我們聊一聊HTTP中的緩存。
想了解更多關于Web性能優化的知識,請移步:
Web前端性能優化:JAVAScript細節篇
Web前端性能優化:html、css、js篇
高級Web必備:網絡優化,拿去鎮住面試官
更過更全內容,歡迎star我的GitHub:https://github.com/programmer-zhang/front-end/
正文
一、緩存的概念知識
- 緩存的分類:服務器緩存(代理服務器緩存、CDN 緩存)、第三方緩存、瀏覽器緩存等。
- 緩存的相關術語:
- 緩存命中率:從緩存中得到數據的請求數與所有請求數的比率。理想狀態是越高越好。
- 過期內容:超過設置的有效時間,被標記為 '陳舊' 的內容。通常過期內容不能用于回復客戶端的請求,必須重新向源服務器請求新的內容或者驗證緩存的內容是否仍然可用。
- 驗證:驗證緩存中的過期內容是否仍然有效,驗證通過的話刷新過期時間或策略。
- 失效:失效就是把內容從緩存中移除。當內容發生改變時就必須移除失效的內容。
- 另: 瀏覽器緩存是代價最小的,因為瀏覽器緩存依賴的是客戶端,而幾乎不耗費服務器端的資源(極端情況下相當于純靜態頁面)。
二、 緩存的作用
- 減少網絡帶寬消耗
- 降低服務器壓力
- 減少網絡延遲,加快頁面打開速度
三、 緩存機制
- 強緩存優先于協商緩存,強緩存生效則使用強緩存,若強緩存失敗,則進行協商緩存
- 協商緩存由服務器決定是否使用緩存,若協商緩存失效,那么代表該請求的緩存失效,重新獲取請求結果,再存入瀏覽器緩存中;生效則返回304,繼續使用緩存
緩存策略 圖片來源:IMWeb前端
四、涉及緩存機制的HTTP-header
4.1、Expires(過期時間)(強緩存機制)
- 值:是一個GMT時間格式的絕對時間,Expires 的日期時間必須是格林威治時間(GMT),而不是本地時間。舉例:Expires: Fri, 30 Oct 1998 14:19:41
- 作用:告訴緩存器相關副本在多長時間內是新鮮的。過了這個時間,緩存器就會向源服務器發送請求,檢查文檔是否被修改。
- 兼容性:幾乎所有的緩存服務器都支持Expires(過期時間)屬性
- 規則:基于客戶最后查看副本的時間(最后訪問時間)或者根據服務器上文檔最后被修改的時間
- 應用:
- 對于設置靜態圖片文件(例如導航欄和圖片按鈕)緩存特別有用;因為這些圖片修改很少,你可以給它們設置一個特別長的過期時間,這會使你的網站對用戶變得相應非常快
- 對于控制有規律改變的網頁也很有用,例如:你每天早上6點更新新聞頁,你可以設置副本的過期時間也是這個時間,這樣緩存服務器就知道什么時候去取一個更新版本,而不必讓用戶去按瀏覽器的"刷新"按鈕。
- 過期時間頭信息屬性值只能是HTTP格式的日期時間,其他的都會被解析成當前時間"之前",副本會過期
- 局限性:雖然過期時間屬性非常有用,但是它還是有些局限,
- 首先:是牽扯到了日期,這樣Web服務器的時間和緩存服務器的時間必須是同步的,如果有些不同步,要么是應該緩存的內容提前過期了,要么是過期結果沒及時更新。
- 如果你設置的過期時間是一個固定的時間,如果你返回內容的時候又沒有連帶更新下次過期的時間,那么之后所有訪問請求都會被發送給源Web服務器,反而增加了負載和響應時間
4.2、Cache-Control(緩存控制)(強緩存機制)
- 值:max-age=[秒] — 執行緩存被認為是最新的最長時間。
- 相對時間,不是絕對時間
- 單位是秒:從請求時間 開始到過期時間之間的秒數。
- 作用:讓網站的發布者可以更全面的控制他們的內容,并定位過期時間的限制。是http 1.1中為了彌補 Expires 缺陷新加入的。
- 相關控制字段:
- s-maxage=[秒] — 類似于max-age屬性,除了他應用于共享(如:代理服務器)緩存
- public — 標記認證內容也可以被緩存,一般來說: 經過HTTP認證才能訪問的內容,輸出是自動不可以緩存的;
- no-cache — 強制每次請求直接發送給源服務器,而不經過本地緩存版本的校驗。這對于需要確認認證應用很有用(可以和public結合使用),或者嚴格要求使用最新數據 的應用(不惜犧牲使用緩存的所有好處);
- no-store — 強制緩存在任何情況下都不要保留任何副本
- must-revalidate — 告訴緩存必須遵循所有你給予副本的新鮮度的
- proxy-revalidate — 和 must-revalidate 類似,除了他只對緩存代理服務器起作用
4.3、Last-Modified/If-Modified-Since (協商緩存機制)
- 通常服務器知道你所請求的數據的最后修改時間,并且 HTTP 為服務器提供了一種將最近修改數據連同你請求的數據一同發送的方法。
- 如果你第二次 (或第三次,或第四次) 請求相同的數據,告訴服務器上一次獲得的最后修改日期:在請求中發送一個 If-Modified-Since 頭信息,它包含了上一次從服務器連同數據所獲得的日期。
- 如果數據從那時起沒有改變,服務器將返回一個特殊的 HTTP 狀態代碼 304,這意味著 “從上一次請求后這個數據沒有改變”。
- 當服務器發送狀態編碼 304 時,不再重新發送數據。所以當數據沒有更新時,你不需要一次又一次地下載相同的數據
- 兼容性 :所有現代的瀏覽器都支持 (last-modified) 的數據檢查。
4.4、ETag/If-None-Match (協商緩存機制)
- 作用: 沒有變化時不重新下載數據
- 工作方式 :
- 1.Etag是上一次加載資源時,服務器返回的 response header,是對該資源的一種唯一標識,只要資源有變化,Etag就會重新生成
- 2.瀏覽器在下一次加載資源向服務器發送請求時,會將上一次返回的 Etag 值放到 request header 里的 If-None-Match 里,服務器比較客戶端傳來的 If-None-Match 跟自己服務器上該資源的 ETag 是否一致
- 3.如果服務器發現 ETag 匹配不上,那么直接以常規 GET 200 回包形式將新的資源(當然也包括了新的 ETag )發給客戶端;如果 ETag 是一致的,則直接返回304知會客戶端直接使用本地緩存即可。
五、幾種緩存策略的對比
5.1、兩種強緩存機制對比 `Expires` VS `Cache-Control`
- 差別不大,區別就是 Expires 是 HTTP1.0 的產物,而 Cache-Control 是 HTTP1.1 的產物
- 優先級上,兩者同時存在的話,Cache-Control 優先級高于 Expires ,Expires 更像是一種備選方案,在某些不支持 Cache-Control 的環境中發揮作用
- 二者共同的弊端 就是這種強緩存的機制僅僅關心緩存是否超出或者超過某個過期時間,并不關心服務器端的資源是否已經更新,所以單純使用這兩種緩存策略會導致客戶端拿到的資源不是最新的
5.2、兩種協商緩存機制對比 `Last-Modified/If-Modified-Since` VS `ETag/If-None-Match`
- 精度上,ETag 要明顯優于前者,Last-Modified/If-Modified-Since 策略的時間單位為秒,這就意味著在秒級的請求上,做不到真正的及時更新,但是 ETag 每次請求都會對其進行改變從而確保精度,并且在使用負載均衡的服務器上,各個服務器生成的 Last-Modified 也有可能不相同
- 性能上,ETag 要遜于 Last-Modified/If-Modified-Since 策略,畢竟 Last-Modified/If-Modified-Since 策略只是記錄時間,而 ETag 需要進行一步hash運算
- 優先級上,服務器會優先考慮 ETag
六、用戶行為對緩存策略的影響
并不是所有的操作都會啟用正常的緩存機制,在某些用戶行為下,緩存機制是可以正常跳過的
- 地址欄訪問,鏈接跳轉是正常用戶行為,將會觸發瀏覽器緩存機制
- F5刷新,瀏覽器會設置max-age=0,跳過強緩存判斷,會進行協商緩存判斷
- ctrl+F5刷新,跳過強緩存和協商緩存,直接從服務器拉取資源
尾聲
既然選擇了遠方,那學就完了。