淺談HTTP緩存

一、HTTP緩存概述(HTTP Cache)

要搞清楚HTTP緩存,首先當(dāng)然是要搞清楚緩存是啥,按照MDN的描述,緩存是這樣的:

緩存是一種保存資源副本并在下次請求時直接使用該副本的技術(shù)。當(dāng) web 緩存發(fā)現(xiàn)請求的資源已經(jīng)被存儲,它會攔截請求,返回該資源的拷貝,而不會去源服務(wù)器重新下載。這樣帶來的好處有:緩解服務(wù)器端壓力,提升性能(獲取資源的耗時更短了)。對于網(wǎng)站來說,緩存是達(dá)到高性能的重要組成部分。緩存需要合理配置,因為并不是所有資源都是永久不變的:重要的是對一個資源的緩存應(yīng)截止到其下一次發(fā)生改變(即不能緩存過期的資源)。

上面已經(jīng)將會緩存是什么描述的很清楚了,而HTTP緩存顧名思義,就是通過HTTP協(xié)議,來實現(xiàn)對資源緩存的目的。總的來說,HTTP緩存主要通過兩個HTTP頭來實現(xiàn)的,其中Expires是由HTTP1.0提供的,而Cache-Control則是由HTTP1.1所提供的:

[站外圖片上傳中...(image-5141a-1538142159770)]

下面我們就來對這兩個頭進行一個了解。

二、Expires

Expires是由HTTP1.0所提供的支持HTTP緩存的頭部,由服務(wù)器返回,用GMT格式的字符串表示:

expires: Tue, 14 Aug 2018 14:32:49 GMT

而讀取緩存的條件則是:緩存過期時間(服務(wù)器的時間)< 當(dāng)前時間(客戶端的時間)

值得注意的是,我們在expires所設(shè)置的時間是一個絕對的時間,而且所參照的是用戶電腦上所設(shè)置的時間。這種絕對的時間很容易出問題,當(dāng)用戶本地的時間不準(zhǔn)確,或用戶進行跨時區(qū)的移動時,這個時間很可能就會過期,而無法發(fā)揮它本應(yīng)該發(fā)揮的作用。

其次,在HTTP1.0里,沒有提供相應(yīng)的配置緩存的方法,只是提供了這個強緩存的頭部而已,不足以滿足項目對緩存多樣化的需求。也正是出于以上兩個原因,在HTTP1.1中對HTTP緩存又進行了升級。

三、 Cache-Control

正是由于Expires存在著很多不足,所以HTTP1.1又為我們提供了

Cache-Control主要可配置的參數(shù)有以下幾個:

  1. max-age 會指定從請求的時間開始,允許獲取的響應(yīng)被重用的最長時間(單位:秒)。例如,“max-age=60”表示可在接下來的 60 秒緩存和重用響應(yīng)。
  2. Public 表示響應(yīng)可被任何緩存區(qū)緩存
  3. Private 表示對于單個用戶的整個或部分響應(yīng)消息,不能被共享緩存處理。這些響應(yīng)通常只為單個用戶緩存,因此不允許任何中間緩存對其進行緩存。例如,用戶的瀏覽器可以緩存包含用戶私人信息的 HTML 網(wǎng)頁,但 CDN 卻不能緩存。
  4. no-cache 表示必須先與服務(wù)器確認(rèn)返回的響應(yīng)是否發(fā)生了變化,然后才能使用該響應(yīng)來滿足后續(xù)對同一網(wǎng)址的請求。因此,如果存在合適的驗證,no-cache 會發(fā)起往返通信來驗證緩存的響應(yīng),但如果資源未發(fā)生變化,則可避免下載。
  5. no-store則要簡單得多。它直接禁止瀏覽器以及所有中間緩存存儲任何版本的返回響應(yīng),例如,包含個人隱私數(shù)據(jù)或銀行業(yè)務(wù)數(shù)據(jù)的響應(yīng)。每次用戶請求該資產(chǎn)時,都會向服務(wù)器發(fā)送請求,并下載完整的響應(yīng)。
  6. min-fresh 表示客戶端可以接收響應(yīng)時間小于當(dāng)前時間加上指定時間的響應(yīng)。(用的不多)
  7. max-stale 表示客戶端可以接收超出超時期間的響應(yīng)消息。如果指定max-stale消息的值,那么客戶機可以接收超出超時期指定值之內(nèi)的響應(yīng)消息。(用的不多)

四、強緩存

上面已經(jīng)將Catch-Control做了一個簡單的介紹,而具體使用它們二者進行緩存操作的具體實現(xiàn)又分為強緩存與協(xié)商緩存。首先來聊一聊強緩存。

強緩存是利用Expires或者Cache-Control這兩個http response header實現(xiàn)的,它們都用來表示資源在客戶端緩存的有效期。在這個有效期內(nèi)當(dāng)瀏覽器對某個資源的請求命中了強緩存時,其返回的http狀態(tài)為200,并且不會去對服務(wù)器進行請求,而是直接使用其本地的緩存。

具體實現(xiàn)如下:

expires: Tue, 21 Aug 2018 10:17:45 GMT
cache-control: max-age=691200

只要存在以上兩個頭部信息的其中一個,我們就可以對資源進行強緩存了。另外需要注意的是,當(dāng)Catch-Control的優(yōu)先級是要高于expires的。

總的來說,強緩存是前端性能優(yōu)化的一大助力。當(dāng)我們頁面存在很多長期不變的靜態(tài)資源時,都應(yīng)該對其進行強緩存的處理,我們通??梢詾檫@些靜態(tài)資源全部配置一個超時時間很長的Expires或Cache-Control。當(dāng)用戶在訪問網(wǎng)頁時,就只會在第一次加載時從服務(wù)器請求靜態(tài)資源,在往后訪問該頁面時,就只要緩存沒有失效并且用戶沒有強制刷新的條件下都會從自己的緩存中加載。這樣既節(jié)省了資源加載的時間的消耗,又不會去訪問服務(wù)器,可以有效地為服務(wù)器減壓。

不過強緩存也存在一個很大的弊端,那就是對于動態(tài)資源它就有點力不從心了。因為如果我們對動態(tài)資源進行了強緩存,那么很可能會在這動態(tài)資源更改后,瀏覽器還是會直接去請求沒有更改前的動態(tài)資源。也這是由于這方面的考慮,在強緩存外還存在著協(xié)商緩存的緩存方案。

五、協(xié)商緩存

當(dāng)瀏覽器對某個資源的請求沒有命中強緩存,就會發(fā)一個請求到服務(wù)器,驗證協(xié)商緩存是否命中,如果協(xié)商緩存命中,請求響應(yīng)返回的http狀態(tài)為304并且會顯示一個Not Modified的字符串;
若未命中請求,則將資源返回客戶端,并更新本地緩存數(shù)據(jù),并返回200的狀態(tài)碼。

除此之外,我們也可以設(shè)置為協(xié)商緩存,以解決動態(tài)資源緩存與更新的問題,首先我們來看一張關(guān)于協(xié)商緩存的圖:

輸入圖片說明

可以看到,在這個實現(xiàn)了協(xié)商緩存的Cache-Control中,設(shè)置了no-catch,當(dāng)我們設(shè)置為no-catch時,我們就是可以直接去訪問服務(wù)器,去查看該資源的更改情況,已確定是是否需要使用緩存。而在校驗的這一步我們就需要使用以下幾個頭來幫助驗證資源的更改情況了:

  • Last-Modified:表示這個響應(yīng)資源的最后修改時間。web服務(wù)器在響應(yīng)請求時,會告訴瀏覽器該資源的最后修改時間,但它的最小單位是秒級,也就是如果我們在1秒內(nèi)多次修改該資源,那么Last-Modified也無法發(fā)揮其應(yīng)有的作用。
  • If-Modified-Since:當(dāng)資源過期時(強緩存失效),發(fā)現(xiàn)資源具有Last-Modified聲明,則再次向web服務(wù)器請求時帶上頭 If-Modified-Since,表示請求時間。web服務(wù)器收到請求后發(fā)現(xiàn)有頭If-Modified-Since 則與被請求資源的最后修改時間進行比對。若最后修改時間較新,說明資源又被改動過,則響應(yīng)整片資源內(nèi)容(寫在響應(yīng)消息包體內(nèi)),HTTP 200;若最后修改時間較舊,說明資源無新修改,則響應(yīng)HTTP 304 (無需包體,節(jié)省瀏覽),告知瀏覽器繼續(xù)使用所保存的cache。

也正是由于 Last-Modified存在著缺陷,我們就需要ETag來幫助我們來對資源的更改進行判斷:

  • Etag:當(dāng)Web服務(wù)器響應(yīng)請求時,會告訴瀏覽器當(dāng)前資源在服務(wù)器的唯一標(biāo)識(生成規(guī)則是由服務(wù)器決定的)。就比如在Apache中,ETag的值,其默認(rèn)是對文件的索引節(jié)(INode),大?。⊿ize)和最后修改時間(MTime)進行Hash后得到的。
  • If-None-Match:當(dāng)資源過期時,如果發(fā)現(xiàn)資源具有Etage聲明,則再次向web服務(wù)器請求時帶上頭If-None-Match (Etag的值)。Web服務(wù)器收到請求后發(fā)現(xiàn)有頭If-None-Match, 就會將其被請求的資源的相應(yīng)校驗字段進行對比,然后再決定返回200或304。

這就是強緩存與協(xié)商緩存的大部分情況了,具體的流程可見下圖:

[站外圖片上傳中...(image-3d76ca-1538142159770)]

原圖鏈接:http://juanha.coding.me/2017/03/05/http-cache/http-cache.png

六、定義最佳 Cache-Control 策略

[站外圖片上傳中...(image-32ca02-1538142159771)]

通常我們可以按照上面這張流程圖來對HTTP緩存進行相應(yīng)的配置,詳情可以看這篇文章:

https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?

這位大佬對緩存的配置做了一個很好的闡述。

參考資料:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容