HTTP之緩存

緩存已獲取的資源可以有效的提高網站與應用的性能,Web 緩存可以減小延遲與網絡阻塞,進而減小顯示某個資源所用的時間。藉助 HTTP 緩存,Web 站點變得更具備響應性。node


咱們來看下與緩存相關的HTTP首部字段算法

請求首部字段

字段名稱 說明
Cache-Control 控制緩存的行爲
Pragma HTTP/1.0遺留物,Pragma: no-cache等同於Cache-Control: no-cache
If-Match 比較ETag是否一致(若是匹配中)
If-None-Match 比較ETag是否不一致(若是未匹配中)
If-Modified-Since 比較Last-Modified時間是否一致
If-Unmodified-Since 比較Last-Modified時間是否一致

響應首部字段

字段名稱 說明
Cache-Control 控制緩存的行爲
Pragma HTTP/1.0遺留物,Pragma: no-cache等同於Cache-Control: no-cache
Expires 過時日期/時間
Last-Modified 資源最後一次修改日期/時間
ETag 資源的特定版本的標識符
Vary
Pragma

Pragma是一個在 HTTP/1.0 中規定的通用首部,這個首部的效果依賴於不一樣的實現,因此在「請求-響應」鏈中可能會有不一樣的效果。當該字段值爲no-cache的時候,與 Cache-Control: no-cache 效果一致,表示禁用緩存。瀏覽器

Expires

Expires的值對應一個GMT(格林尼治時間)來告訴瀏覽器資源緩存過時時間,若是還沒到該時間點則不發請求。緩存

Expires所定義的緩存時間是相對服務器上的時間而言的,要求客戶端和服務器端的時鐘嚴格同步。客戶端的時間是能夠修改的,若是服務器和客戶端的時間不統一,這就致使有可能出現緩存提早失效的狀況,存在不穩定性。 面對這種狀況,HTTP1.1引入了 Cache-Control 頭來克服 Expires 頭的限制。bash

若是在Cache-Control響應頭設置了 "max-age" 或者 "s-max-age",那麼 Expires 頭會被忽略。服務器


Pragma 和 Expires 如今主要用來用來向後兼容只支持 HTTP/1.0 協議的緩存服務器。網絡

Cache-Control

Cache-Control 是一個通用首部字段,被用於在http請求和響應中。緩存指令是單向的,這意味着在請求中設置的指令,不必定被包含在響應中分佈式

客戶端能夠在HTTP請求中使用的標準 Cache-Control 指令性能

Cache-Control 屬性值 說明
no-cache 告知服務器不直接使用緩存
no-store 資源不會保存到緩存/臨時文件
no-transform 代表客戶端但願獲取實體數據沒有被轉換
max-age=[seconds] 代表客戶端願意接收一個帶緩存時間的資源
max-stale[=seconds] 代表客戶端願意接收一個已通過期的資源。能夠設置一個可選的秒數,表示響應不能已通過時超過該給定的時間
min-fresh=[seconds] 代表客戶端但願接收一個能在seconds秒內被更新過的資源
only-if-cached 代表客戶端只接受已緩存的響應,而且不向原服務器檢查是否有更新

服務器能夠在響應中使用的標準 Cache-Control 指令網站

Cache-Control 屬性值 說明
no-cache 不使用緩存,要求向服務器發起請求
no-store 資源不該該存儲到客戶端緩存/臨時文件
no-transform 不能對資源進行轉換或轉變。HTTP頭/實體 不能由代理修改
public 代表響應能夠被任何對象(包括:發送請求的客戶端,代理服務器等)緩存,即便是一般不可緩存的內容(例如,該響應沒有max-age指令或Expires消息頭)
private 代表響應只能被單個用戶緩存,不能做爲共享緩存(即代理服務器不能緩存它)
must-revalidate 一旦資源過時(好比已經超過max-age),必須向原服務器驗證請求
proxy-revalidate 與must-revalidate相似,但僅適用於共享緩存(如代理)
max-age=[seconds] 設置緩存存儲的最大週期,超過這個時間緩存被認爲過時(單位秒)
s-maxage=[seconds] 覆蓋max-age,但僅限於共享緩存(如代理)

Cache-Control 容許自由組合可選值,例如:

Cache-Control: public, max-age=3600, must-revalidate
複製代碼

緩存驗證

用戶點擊刷新按鈕時會開始緩存驗證

若是緩存的響應頭信息裏含有"Cache-control: must-revalidate」的定義,在瀏覽的過程當中也會觸發緩存驗證

當緩存的文檔過時後,須要進行緩存驗證或者從新獲取資源。只有在服務器返回 弱校驗器(Last-Modified) 或者 強校驗器(ETag)時纔會進行驗證。

1. Last-Modified

Last-Modified 響應頭能夠做爲一種弱校驗器,其值爲資源最後更改的時間

Last-Modified: Tue Aug 20 2019 15:47:05 GMT
複製代碼

若是響應頭裏含有Last-Modified,客戶端能夠在後續的請求首部帶上 If-Modified-Since 或者 If-Unmodified-Since 驗證Last-Modified

If-Modified-Since:若客戶端傳遞的時間值與服務器上該資源最後修改時間是一致(If-Modified-Since==Last-Modified),則說明該資源沒有被修改過,直接返回304狀態碼,內容爲空,這樣就節省了傳輸數據量 。若是兩個時間不一致,則服務器會發回該完整資源並返回200狀態碼,和第一次請求時相似。這樣保證不向客戶端重複發出資源,也保證當服務器有變化時,客戶端可以獲得最新的資源。一個304響應比一個靜態資源一般小得多,這樣就節省了網絡帶寬。 當前各瀏覽器均是使用If-Modified-Since請求首部來向服務器傳遞保存的 Last-Modified 值

If-Unmodified-Since:該值告訴服務器,若Last-Modified沒有匹配上(資源在服務端的最後更新時間改變了),則應當返回412(Precondition Failed) 狀態碼給客戶端

Last-Modified 稱爲弱校驗器 由於它不夠準確:

  • 只能精確到一秒,在1秒內資源改變,由於時間比較相同,而不會去更新最新的資源
  • 一個資源被修改了,但其實際內容根本沒發生改變,會由於Last-Modified時間匹配不上而返回了整個實體給客戶端(即便客戶端緩存裏有個如出一轍的資源)

2. ETag

ETag能夠解決上述Last-Modified可能存在的不許確的問題,於是稱它爲強校驗器 ETag值爲一個惟一標識符,服務器利用文件修改時間、文件大小和inode號等經過某種算法計算得出

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
複製代碼

若是響應頭裏含有ETag,客戶端能夠在後續的請求首部帶上 If-Match 或者 If-None-Match 驗證ETag

If-None-Match:若是服務器發現ETag不匹配(If-None-Match!=ETag),那麼直接以常規GET 200回包形式將新的資源(固然也包括了新的ETag)發給客戶端。若客戶端傳遞的etag跟服務器的etag一致,則直接返回304知會客戶端直接使用本地緩存便可; 當前各瀏覽器均是使用If-Match請求首部來向服務器傳遞保存的 ETag 值

If-Match:告訴服務器若是沒有匹配到ETag,或者收到了「*」值而當前並無該資源實體,則應當返回412(Precondition Failed) 狀態碼給客戶端。不然服務器直接忽略該字段

須要注意的是,若是資源是走分佈式服務器(好比CDN)存儲的狀況,須要這些服務器上計算ETag惟一值的算法保持一致,纔不會致使明明同一個文件,在服務器A和服務器B上生成的ETag卻不同

相關文章
相關標籤/搜索