http緩存(原理、機制、配置)

http緩存機制

背景

http緩存指的是: 當客戶端向服務器請求資源時,會先抵達瀏覽器緩存,若是瀏覽器有「要請求資源」的副本,就能夠直接從瀏覽器緩存中提取而不是從原始服務器中提取這個資源。node

常見的http緩存只能緩存get請求響應的資源,對於其餘類型的響應則無能爲力,因此後續說的請求緩存都是指GET請求。nginx

http緩存都是從第二次請求開始的。第一次請求資源時,服務器返回資源,並在respone header頭中回傳資源的緩存參數;第二次請求時,瀏覽器判斷這些請求參數,命中強緩存就直接200,不然就把請求參數加到request header頭中傳給服務器,看是否命中協商緩存,命中則返回304,不然服務器會返回新的資源。segmentfault

強緩存

瀏覽器在請求某一資源時,會先獲取該資源緩存的header信息,判斷是否命中強緩存(cache-control和expires信息),若命中直接從緩存中獲取資源信息,包括緩存header信息;本次請求根本就不會與服務器進行通訊。
狀態碼爲200瀏覽器

Expires

Expires是http1.0的規範,它的值是一個絕對時間的GMT格式的時間字符串,這個時間表明這這個資源的失效時間,只要發送請求時間是在Expires以前,那麼本地緩存始終有效,則在緩存中讀取數據。失效的時間是一個絕對時間,當服務器與客戶端時間誤差較大時,會致使緩存混亂。若是同時出現Cache-Control:max-age和Expires,那麼max-age優先級更高。緩存

Cache-Control

Cache-Control是在http1.1中出現的,主要是利用該字段的max-age值來進行判斷,它是一個相對時間,例如Cache-Control:max-age=3600,表明着資源的有效期是3600秒。cache-control除了該字段外,還有下面幾個比較經常使用的設置值:服務器

類型 描述
public 客戶端和代理服務器均可以緩存該資源;客戶端在xxx秒的有效期內,若是有請求該資源的需求的話就直接讀取緩存,status code:200 ,若是用戶作了刷新操做,就向服務器發起http請求
private 只讓客戶端能夠緩存該資源,代理服務器不緩存;客戶端在xxx秒內直接讀取緩存,status code:200
immutable 客戶端在xxx秒的有效期內,若是有請求該資源的需求的話就直接讀取緩存,status code:200 ,即便用戶作了刷新操做,也不向服務器發起http請求
no-cache 跳過設置強緩存,可是不妨礙設置協商緩存;通常若是你作了強緩存,只有在強緩存失效了才走協商緩存的,設置了no-cache就不會走強緩存了,每次請求都回詢問服務端
no-store 不緩存,這個會讓客戶端、服務器都不緩存,也就沒有所謂的強緩存、協商緩存了

協商緩存

若是沒有命中強緩存,瀏覽器會發送請求到服務器,請求會攜帶第一次請求返回的有關緩存的header字段信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),由服務器根據請求中的相關header信息來比對結果是否協商緩存命中;若命中,則服務器返回新的響應header信息更新緩存中的對應header信息,可是並不返回資源內容,它會告知瀏覽器能夠直接從緩存獲取;不然返回最新的資源內容。
狀態碼爲304編碼

last-modified

last-modified記錄資源最後修改的時間。啓用強緩存後,請求資源以後的響應頭會增長一個last-modified字段,當再次請求該資源時,請求頭中會帶有if-modified-since字段,值是以前返回的last-modified的值。服務端會對比該字段和資源的最後修改時間,若一致則證實沒有被修改,告知瀏覽器可直接使用緩存並返回 304;若不一致則直接返回修改後的資源,並修改last-modified爲新的值。spa

last-modified 有如下兩個缺點:代理

  • 只要編輯了,無論內容是否真的有改變,都會以這最後修改的時間做爲判斷依據,當成新資源返回,從而致使了不必的請求響應,而這正是緩存原本的做用即避免不必的請求。
  • 時間的精確度只能到秒,若是在一秒內的修改是檢測不到更新的,仍會告知瀏覽器使用舊的緩存。

etag

爲了解決 last-modified 上述問題,有了 etagetag 會基於資源的內容編碼生成一串惟一的標識字符串,只要內容不一樣,就會生成不一樣的 etag。啓用 etag 以後,請求資源後的響應返回會增長一個 etag 字段,當再次請求該資源時,請求頭會帶有if-no-match字段,值是以前返回的etag值,服務端會根據該資源當前的內容生成對應的標識字符串和該字段進行對比,若一致則表明未改變可直接使用本地緩存並返回 304;若不一致則返回新的資源(狀態碼200)並修改返回的 etag 字段爲新的值。code

能夠看出 etaglast-modified 更加精準地感知了變化,因此 etag 優先級也更高。不過從上面也能夠看出 etag 存在的問題,就是每次生成標識字符串會增長服務器的開銷。因此要如何使用 last-modifiedetag 還須要根據具體需求進行權衡。

機制

clipboard.png

一、用戶發起了一個http請求後,瀏覽器顯示經過強緩存機制檢測瀏覽器中該資源是否有緩存,有則直接返回資源,狀態碼爲200,而且不會請求服務器。
二、假若強緩存失效後,瀏覽器會向服務器請求資源,服務器會根據瀏覽器帶過來的請求頭信息進行協商緩存的檢測,若協商緩存有效則直接返回資源,狀態碼爲304.
三、當協商緩存也失效後,服務器從新獲取資源返回給瀏覽器,狀態碼爲200。

如何設置緩存

node等服務端設置

res.setHeader('max-age': '3600 public')  
res.setHeader(etag: '5c20abbd-e2e8')  
res.setHeader('last-modified': Mon, 24 Dec 2018 09:49:49 GMT)

nginx設置

image.png

本文參考:
http://www.javashuo.com/article/p-axzbmxqe-w.html
https://www.jianshu.com/p/9c95db596df5

相關文章
相關標籤/搜索