浅谈HTTP缓存
一、HTTP緩存概述(HTTP Cache)
要搞清楚HTTP緩存,首先當然是要搞清楚緩存是啥,按照MDN的描述,緩存是這樣的:
緩存是一種保存資源副本并在下次請求時直接使用該副本的技術。當 web 緩存發現請求的資源已經被存儲,它會攔截請求,返回該資源的拷貝,而不會去源服務器重新下載。這樣帶來的好處有:緩解服務器端壓力,提升性能(獲取資源的耗時更短了)。對于網站來說,緩存是達到高性能的重要組成部分。緩存需要合理配置,因為并不是所有資源都是永久不變的:重要的是對一個資源的緩存應截止到其下一次發生改變(即不能緩存過期的資源)。
上面已經將會緩存是什么描述的很清楚了,而HTTP緩存顧名思義,就是通過HTTP協議,來實現對資源緩存的目的??偟膩碚f,HTTP緩存主要通過兩個HTTP頭來實現的,其中Expires是由HTTP1.0提供的,而Cache-Control則是由HTTP1.1所提供的:
下面我們就來對這兩個頭進行一個了解。
二、Expires
Expires是由HTTP1.0所提供的支持HTTP緩存的頭部,由服務器返回,用GMT格式的字符串表示:
expires: Tue, 14 Aug 2018 14:32:49 GMT 復制代碼而讀取緩存的條件則是:緩存過期時間(服務器的時間)< 當前時間(客戶端的時間)
值得注意的是,我們在expires所設置的時間是一個絕對的時間,而且所參照的是用戶電腦上所設置的時間。這種絕對的時間很容易出問題,當用戶本地的時間不準確,或用戶進行跨時區的移動時,這個時間很可能就會過期,而無法發揮它本應該發揮的作用。
其次,在HTTP1.0里,沒有提供相應的配置緩存的方法,只是提供了這個強緩存的頭部而已,不足以滿足項目對緩存多樣化的需求。也正是出于以上兩個原因,在HTTP1.1中對HTTP緩存又進行了升級。
三、 Cache-Control
正是由于Expires存在著很多不足,所以HTTP1.1又為我們提供了
Cache-Control主要可配置的參數有以下幾個:
四、強緩存
上面已經將Catch-Control做了一個簡單的介紹,而具體使用它們二者進行緩存操作的具體實現又分為強緩存與協商緩存。首先來聊一聊強緩存。
強緩存是利用Expires或者Cache-Control這兩個http response header實現的,它們都用來表示資源在客戶端緩存的有效期。在這個有效期內當瀏覽器對某個資源的請求命中了強緩存時,其返回的http狀態為200,并且不會去對服務器進行請求,而是直接使用其本地的緩存。
具體實現如下:
expires: Tue, 21 Aug 2018 10:17:45 GMT cache-control: max-age=691200 復制代碼只要存在以上兩個頭部信息的其中一個,我們就可以對資源進行強緩存了。另外需要注意的是,當Catch-Control的優先級是要高于expires的。
總的來說,強緩存是前端性能優化的一大助力。當我們頁面存在很多長期不變的靜態資源時,都應該對其進行強緩存的處理,我們通常可以為這些靜態資源全部配置一個超時時間很長的Expires或Cache-Control。當用戶在訪問網頁時,就只會在第一次加載時從服務器請求靜態資源,在往后訪問該頁面時,就只要緩存沒有失效并且用戶沒有強制刷新的條件下都會從自己的緩存中加載。這樣既節省了資源加載的時間的消耗,又不會去訪問服務器,可以有效地為服務器減壓。
不過強緩存也存在一個很大的弊端,那就是對于動態資源它就有點力不從心了。因為如果我們對動態資源進行了強緩存,那么很可能會在這動態資源更改后,瀏覽器還是會直接去請求沒有更改前的動態資源。也這是由于這方面的考慮,在強緩存外還存在著協商緩存的緩存方案。
五、協商緩存
當瀏覽器對某個資源的請求沒有命中強緩存,就會發一個請求到服務器,驗證協商緩存是否命中,如果協商緩存命中,請求響應返回的http狀態為304并且會顯示一個Not Modified的字符串; 若未命中請求,則將資源返回客戶端,并更新本地緩存數據,并返回200的狀態碼。
除此之外,我們也可以設置為協商緩存,以解決動態資源緩存與更新的問題,首先我們來看一張關于協商緩存的圖:
可以看到,在這個實現了協商緩存的Cache-Control中,設置了no-catch,當我們設置為no-catch時,我們就是可以直接去訪問服務器,去查看該資源的更改情況,已確定是是否需要使用緩存。而在校驗的這一步我們就需要使用以下幾個頭來幫助驗證資源的更改情況了:
- Last-Modified:表示這個響應資源的最后修改時間。web服務器在響應請求時,會告訴瀏覽器該資源的最后修改時間,但它的最小單位是秒級,也就是如果我們在1秒內多次修改該資源,那么Last-Modified也無法發揮其應有的作用。
- If-Modified-Since:當資源過期時(強緩存失效),發現資源具有Last-Modified聲明,則再次向web服務器請求時帶上頭 If-Modified-Since,表示請求時間。web服務器收到請求后發現有頭If-Modified-Since 則與被請求資源的最后修改時間進行比對。若最后修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最后修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。
也正是由于 Last-Modified存在著缺陷,我們就需要ETag來幫助我們來對資源的更改進行判斷:
- Etag:當Web服務器響應請求時,會告訴瀏覽器當前資源在服務器的唯一標識(生成規則是由服務器決定的)。就比如在Apache中,ETag的值,其默認是對文件的索引節(INode),大小(Size)和最后修改時間(MTime)進行Hash后得到的。
- If-None-Match:當資源過期時,如果發現資源具有Etage聲明,則再次向web服務器請求時帶上頭If-None-Match (Etag的值)。Web服務器收到請求后發現有頭If-None-Match, 就會將其被請求的資源的相應校驗字段進行對比,然后再決定返回200或304。
這就是強緩存與協商緩存的大部分情況了,具體的流程可見下圖:
原圖鏈接:user-gold-cdn.xitu.io/2018/8/16/1…
六、定義最佳 Cache-Control 策略
通常我們可以按照上面這張流程圖來對HTTP緩存進行相應的配置,詳情可以看這篇文章:
developers.google.com/web/fundame…?
這位大佬對緩存的配置做了一個很好的闡述。
原文鏈接:srtian96.gitee.io/blog/2018/0…
參考資料:
- developers.google.com/web/fundame…?
- www.cnblogs.com/lyzg/p/5125…
- developer.mozilla.org/zh-CN/docs/…
總結
- 上一篇: Code Signal_练习题_extr
- 下一篇: 洛谷P3381 【模板】最小费用最大流