1. 程式人生 > >HTTP緩存總結

HTTP緩存總結

頻繁 oms 移除 tag .com 不變 修改 定義 hash

在具體了解 HTTP 緩存之前先來明確幾個術語:
1、緩存命中率:從緩存中得到數據的請求數與所有請求數的比率。理想狀態是越高越好。
2、過期內容:超過設置的有效時間,被標記為“陳舊”的內容。通常過期內容不能用於回復客戶端的請求,必須重新向源服務器請求新的內容或者驗證緩存的內容是否仍然準備。
3、驗證:驗證緩存中的過期內容是否仍然有效,驗證通過的話刷新過期時間。
4、失效:失效就是把內容從緩存中移除。當內容發生改變時就必須移除失效的內容。

HTML meta標簽定義緩存
例如
<META HTTP-EQUIV="Pragma" CONTENT="no-store">
含義是讓瀏覽器不緩存當前頁面。但是代理服務器不解析 HTML 內容,一般應用廣泛的是用 HTTP 頭信息控制緩存。

(在meta信息中定義緩存的方式對於代理服務器不起作用,所以,我們要用Http頭設置緩存。)

HTTP頭信息控制緩存
大致分為兩種:強緩存和協商緩存。
強緩存命中緩存時,不需要和服務器端發生交互;而協商緩存不管是否命中都要和服務器端發生交互。
強制緩存的優先級高於協商緩存。

強緩存和協商緩存的匹配流程如下圖:

技術分享


下面具體解釋這兩種緩存:
一、強緩存
可以理解為無須驗證的緩存策略。對強緩存來說,響應頭中有兩個字段 Expires/Cache-Control 來表明規則。

Expires
Expires 指緩存過期的時間,超過了這個時間點就代表資源過期。有一個問題是由於使用具體時間,如果時間表示出錯或者沒有轉換到正確的時區都可能造成緩存生命周期出錯。並且 Expires 是 HTTP/1.0 的標準,現在更傾向於用 HTTP/1.1 中定義的 Cache-Control。兩個同時存在時也是 Cache-Control 的優先級更高。


Cache-Control
Cache-Control 可以由多個字段組合而成,主要有以下幾個取值:
1. max-age 指定一個時間長度,在這個時間段內緩存是有效的,單位是s。例如設置 Cache-Control:max-age=31536000,也就是說緩存有效期為(31536000 / 24 / 60 * 60)天,第一次訪問這個資源的時候,服務器端也返回了 Expires 字段,並且過期時間是一年後。

技術分享


在沒有禁用緩存並且沒有超過有效時間的情況下,再次訪問這個資源就命中了緩存,不會向服務器請求資源而是直接從瀏覽器緩存中取。

技術分享


2. s-maxage 同 max-age,覆蓋 max-age、Expires,但僅適用於共享緩存,在私有緩存中被忽略。

3. public 表明響應可以被任何對象(發送請求的客戶端、代理服務器等等)緩存(共享的)。
4. private 表明響應只能被單個用戶(可能是操作系統用戶、瀏覽器用戶)緩存(非共享的),不能被代理服務器緩存。
5. no-cache 強制所有緩存了該響應的用戶,在使用已緩存的數據前,發送帶驗證器的請求到服務器。不是字面意思上的不緩存。
6. no-store 禁止緩存,每次請求都要向服務器重新獲取數據。

二、協商緩存
緩存的資源到期了,並不意味著資源內容發生了改變,如果和服務器上的資源沒有差異,實際上沒有必要再次請求。
客戶端和服務器端通過某種驗證機制驗證當前請求資源是否可以使用緩存。

瀏覽器第一次請求數據之後會將數據和響應頭部的緩存標識存儲起來。再次請求時會帶上存儲的頭部字段,服務器端驗證是否可用。
如果返回 304 Not Modified,代表資源沒有發生改變可以使用緩存的數據,獲取新的過期時間。
反之返回 200 就相當於重新請求了一遍資源並替換舊資源。

Last-modified/If-Modified-Since
Last-modified: 服務器端資源的最後修改時間,響應頭部會帶上這個標識。第一次請求之後,瀏覽器記錄這個時間,再次請求時,請求頭部帶上 If-Modified-Since 即為之前記錄下的時間。服務器端收到帶 If-Modified-Since 的請求後會去和資源的最後修改時間對比。若修改過就返回最新資源,狀態碼 200,若沒有修改過則返回 304。

技術分享


註意:如果響應頭中有 Last-modified 而沒有 Expire 或 Cache-Control 時,瀏覽器會有自己的算法來推算出一個時間緩存該文件多久,不同瀏覽器得出的時間不一樣,所以 Last-modified 要記得配合 Expires/Cache-Control 使用。

Etag/If-None-Match
由服務器端上生成的一段 hash 字符串,第一次請求時響應頭帶上 ETag: abcd,之後的請求中帶上 If-None-Match: abcd,服務器檢查 ETag,返回 304 或 200。

技術分享


關於last-modified和Etag區別,已經有很多人總結過了:
某些服務器不能精確得到資源的最後修改時間,這樣就無法通過最後修改時間判斷資源是否更新。
Last-modified 只能精確到秒。
一些資源的最後修改時間改變了,但是內容沒改變,使用Last-modified看不出內容沒有改變。
Etag的精度比Last-modified高,屬於強驗證,要求資源字節級別的一致,優先級高。如果服務器端有提供ETag的話,必須先對ETag進行Conditional Request。

註意:實際使用ETag/Last-modified要註意保持一致性,做負載均衡和反向代理的話可能會出現不一致的情況。計算ETag也是需要占用資源的,如果修改不是過於頻繁,看自己的需求用 Cache-Control是否可以滿足。

實際應用
回到實際應用上來,首先要明確哪些內容適合被緩存哪些不適合。
考慮緩存的內容:
css樣式文件
js文件
logo、圖標
html文件
可以下載的內容

一些不應該被緩存的內容:
業務敏感的 GET 請求

可緩存的內容又分為幾種不同的情況:
1、不經常改變的文件。
給 max-age 設置一個較大的值,一般設置 max-age=31536000
比如引入的一些第三方文件、打包出來的帶有 hash 後綴 css、js 文件。一般來說文件內容改變了,會更新版本號、hash 值,相當於請求另一個文件。
標準中規定 max-age 的值最大不超過一年,所以設成 max-age=31536000。至於過期內容,緩存區會將一段時間沒有使用的文件刪除掉。
2、可能經常需要變動的文件。
Cache-Control: no-cache/max-age=0
比如入口 index.html 文件、文件內容改變但名稱不變的資源。選擇 ETag 或 Last-Modified 來做驗證,在使用緩存資源之前一定會去服務器端做驗證,命中緩存時會比第一種情況慢一點點,畢竟還要發請求進行通信。

註意: 這裏只描述了最基本的思路,實際使用 HTTP 緩存需要後端配合配置,具體情況具體對待,而且各方的實現並不一定完全按照標準來的,踩踩坑更健康。

相關資料:
也許這樣理解HTTPS更容易 https://mp.weixin.qq.com/s/E5PINP-HmHuUWsszVOG79g
HTTP緩存機制一二三 http://mp.weixin.qq.com/s/EqrFhUTIcqO804NHiqWFsg
淺談 Web 緩存 http://mp.weixin.qq.com/s/MLmxeIlX6Zy7Uy98SEWbFw
前端跨域知識總結 http://mp.weixin.qq.com/s/NOmsbKZsryTUONQj2gBFIA
理解偽元素:before和:after http://mp.weixin.qq.com/s/YUxSKRW98Q2uvqpF6zZ3Vg
前端跨域請求原理及實踐 https://mp.weixin.qq.com/s/CZgz0ya_RXhzDkEfv2_9iw

HTTP緩存總結