天天看點

http協定之用戶端緩存cache-control

作者:甯靜知行者
http協定之用戶端緩存cache-control

cache-control 是通用消息頭字段,被用于http協定中請求與響應中,通過指定指令來實作緩存機制。

cache-control 有以下的屬性,多個可以以逗号分隔

名稱 說明
max-age=<seconds> 設定用戶端緩存的最大周期,超過則被認為是過期
s-maxage=<seconds> 覆寫 max-age,但隻适用于代理伺服器
public 表明響應可以被任何對象緩存,包括代碼伺服器、用戶端
private 表明響應隻能被單個使用者緩存,不能作為共享緩存
no-cache 強制要求緩存把請求送出給原始伺服器進行驗證(協商緩存驗證)
no-store 緩存不應存儲有關用戶端請求或是伺服器響應的任何内容,即不使用任何緩存

max-age 與 s-maxage

cache-control: max-age=N, N 即是緩存的秒數,從第一次請求資源的時候開始計算,之後N秒内,再進行資源請求,則會從本地磁盤或是記憶體中讀取,不會再與伺服器進行任務的互動。

cache-control: s-maxage=N, 是設定代理伺服器可以緩存的時長,機關為秒

no-cache 與 no-store 的使用

no-cache 并不是說不緩存,而是強制進行協商緩存,如果某一個資源 cache-control 中有設定 no-cache, 那麼該資源會跳過強制緩存的校驗,而是會與服務端進行協商緩存,而no-store是禁止所有的緩存政策

public 與 private

這兩個參數是為了指定可以緩存該對象的使用者,請求資源的流程可以是以下兩種

http協定之用戶端緩存cache-control
http協定之用戶端緩存cache-control

如果指定為public,則以上兩種都可以進行緩存。

如果是指定為private,則代理伺服器是不允許進行緩存的。

緩存

基于expires

在http/1.0 使用 Expires 字段來辨別

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2023 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2023 22:00:00 GMT
Cache-Control: max-age=3600           

但因為時間格式比較難解析,也有可能因為用戶端與服務端的時間不同,而引發一些問題,是以在 http/1.1中使用 cache-control: max-age 用于指定經過的時間.

如上面的響應是從2023年2月22日 22:22:22 開始,往後1 小時,這個資源都是可以從本地緩存中擷取(強制緩存),而過時(stale)的資源也不會立即丢棄,會先請求一次進行驗證,會帶上 If-Modified-Since,而這個值就是第一次請求時傳回的 Last-Modified (協商緩存)

GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Tue, 22 Feb 2023 22:00:00 GMT
           

如果沒有變化則是響應 304 Not Modified.

HTTP/1.1 304 Not Modified
Content-Type: text/html
Date: Tue, 22 Feb 2023 23:22:22 GMT
Last-Modified: Tue, 22 Feb 2023 22:00:00 GMT
Cache-Control: max-age=3600           

基于ETag

因為使用 Last-Modified 方式,會存在時間解析,伺服器時間難同步的問題,ETag 方式被提出來,通過生成主體内容的哈希值或是版本号。

如下的響應:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2023 22:22:22 GMT
ETag: "xxtttee"
Cache-Control: max-age=3600           

在一小時内,這個緩存是有效的,可以通路本地的緩存資料(強制緩存),而如果本地緩存失效(stale),則再次請求時會增加請求頭 If-None-Match: "" (協商緩存),而這個值為上次請求時傳回的 ETag,服務端在接收到這個請求後,會比對這個ETag的值,如果相同,則會傳回 狀态碼為 304 ,用戶端可以繼續使用這個緩存在 max-age的時間範圍内,如果ETag有變化,則傳回狀态碼200,并将内容也一同傳回。

GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "xxtttee"           
HTTP/1.1 304 Not Modified           

如果服務端未傳回相應的字段,則浏覽器會使用啟發式的算法,通過響應頭中的Date 減去 Last-Modified 值的 %10 作為緩存時間

總結下流程,如下:

http協定之用戶端緩存cache-control

請求頭中的cache-control

當在請求頭中設定 cache-control 是訓示目前請求應該走什麼樣的緩存政策

cache-control: max-age=0 表示目前的請求按協商緩存的規則走,一定會發出真實的請求

cache-control: no-cache ,一般會附帶 Pragma: no-cache,是為了相容 http/1.0, 表示這次請求不會讀緩存資源,即使緩存沒有過期,也不會攜帶 協商緩存相關的請求頭,是以也不會有304的狀态出現。

在請求頭中的cache-control 也隻能使用上面的兩種值。

總結

  1. 對于頻繁變動的資源可以設定 cache-control: no-cache 進行協商
  2. 不常變動的資源可以設定 cache-control: max-age= 比較大值,如 32536000(一年)

繼續閱讀