http緩存主要分爲了兩類 強緩存(本地緩存)和協商緩存瀏覽器
瀏覽器在請求某一資源時,會先獲取改資源緩存的header信息,判斷是否命中強緩存(expires的信息和cache-control)若命中直接從緩存中獲取該資源信息,包括緩存header信息,本次請求根本就不會與服務器進行通訊。此爲強緩存(本地緩存)緩存
若是沒有命中強緩存,瀏覽器會發送請求到服務器,請求會攜帶第一次請求返回的的有關緩存的header字段信息(last-modified/if-modified-since 和 Etag/if-none-Match),由服務器根據請求中相關header信息來比對結果是否協商緩存命中,若命中,則服務器返回新的響應header信息更新緩存中的對應header信息,可是並不返回資源內容,它會告知瀏覽器能夠直接從緩存獲取,不然返回最新的資源內容。服務器
獲取資源形式 狀態碼 發送請求到服務器
強緩存 從緩存取 200(from cache) 否,直接從緩存取
協商緩存 從緩存取 304(not modified) 是,正如其名,經過服務器來告知緩存是否可用spa
1 expires,這是http1.0的規範,它的值爲一個絕對時間的GMT格式的時間字符串,如Mon, 10 Jun 2015 21:31:12 GMT。若是發送請求的時間在expires以前,那麼本地緩存始終有效,不然就會發送請求到服務器來獲取資源。代理
2 cache-control:max-age=number,這是Http1.1時出現的header信息。主要是利用該字段的max-age值來進行判斷。它是一個相對值,資源第一次的請求時間和cache-control設定的有效期,計算出一個資源過時時間。再拿這個過時時間跟當前的請求時間比較,若是請求時間在過時時間以前,就能命中緩存,不然就不行,cache-control除了該字段外,還有下面幾個比較經常使用的設置值。
no-cache : 不使用本地緩存,須要使用協商緩存。
no-store : 直接禁止瀏覽器緩存數據。(強緩存和協商緩存都不行),每次用戶請求該資源,都會向服務器發送一個請求,每次都會下載完整的資源。(經常使用於銀行等重要業務)
public : 能夠被全部的用戶緩存,包括終端用戶和cdn等中間代理服務器
private : 只能被終端用戶緩存,不容許CDN等中繼緩存服務器對其緩存unix
注意:若是cache-control與expires同時存在的話,cache-control的優先級高於expires。code
協商緩存都是由服務器來肯定緩存資源是否可用的,因此客戶端與服務器端經過某種標識進行通訊,從而讓服務器判斷請求資源是否能夠緩存訪問,
這裏涉及到下面兩組header字段。這兩組搭檔都是成對出現的,即第一次請求的響應頭帶上某個字段(last-modified或者ETag),則後續請求則會帶上對應的請求字段(if-modified-since或者if-none-match),若響應頭沒有last-modified或者Etag字段,則請求頭也不會有對應的字段。cdn
1,第一次和服務器交互,服務器返回資源 在response的header加上last-modified的header.這個header表示這個資源在服務器上的最後修改時間blog
2,第二次請求這個資源,瀏覽器會在request header加上if-modified-since的header.這個header的值就是上一次請求時返回的last-modified的值。服務器再次收到資源請求。根據瀏覽器傳過來的if-modified-since和資源在服務器上的最後修改時間判斷資源是否有變化,若是沒有發生變化則返回
304 not modified .可是不會返回資源內容。若是有變化,就正常返回資源內容和更新last-modified字段。當服務器返回304 not modified的響應時,response header中不會再添加last-modified的字段。由於既然資源沒有變化,那麼last-modified也就不會改變.ip
Etag/if-none-Match
這兩個值是由服務器生產的每個資源的惟一標識字符串,只要資源有變化就這個值就會改變,其判斷過程和last-modified/if-modified-since相似,與last-modified不同的是。當服務器返回304 not
modified的響應 response header中還會把這個etag返回,即便這個eTag跟以前沒有變化。
**Etag比較的是文件資源的特徵值,而Last-Modifield則比較的是文件資源的最後的修改時間。這兩個實際上是相輔相成的,不是有了Etag就不應有Last-Modifield,有了Last-Modifield就不應有Etag,同時傳入服務器時,服務器會根據本身的緩存機制進行選擇要使用哪一個,甚至能夠兩個都進行參考
好比img確定判斷last-modified更方便。其餘文件可能比較etag更方便
**
你可能會以爲使用last-modified已經足以讓瀏覽器知道本地的緩存副本是否足夠新,爲何還要Etag呢。http1.1 etag的出現主要是爲了解決幾個last-modifed比較難解決的問題:
1 一些文件也行會週期性的更改,可是他的內容並不改變(僅僅改變的修改時間),這個時候咱們並不但願客戶端認爲這個文件被修改了,而從新GET;
2 某些文件修改很是頻繁,好比在秒如下的時間內進行修改(比方說1s內修改N次)if-modified-since能檢查到的粒度是s級的,這種修改沒法判斷(unix記錄mtime只能精確到秒)
3 某些服務器不能精確獲得文件的最後修改時間。