天天看點

【前端 · 面試 】HTTP 總結(九)—— HTTP 協商緩存

最近我在做前端面試題總結系列,感興趣的朋友可以添加關注,歡迎指正、交流。

争取每個知識點能夠多總結一些,至少要做到在面試時,針對每個知識點都可以侃起來,不至于啞火。

【前端 · 面試 】HTTP 總結(九)—— HTTP 協商緩存

前言

通過前面的介紹,我們知道 HTTP 緩存分為兩種:

  • 強緩存
  • 協商緩存
【前端 · 面試 】HTTP 總結(九)—— HTTP 協商緩存

在上一篇文章中,我們了解了 HTTP 強緩存,今天我們來了解一下協商緩存相關的内容。

特點

協商緩存,也稱為對比緩存,從名稱可以看出,它沒有強制緩存那麼霸道,可以有商有量的來确定是否使用緩存資源。

協商緩存機制下,浏覽器需要發送緩存辨別,去向伺服器驗證緩存辨別是否有效,進而判斷是重新發起請求、下載下傳完整的響應,還是從本地擷取緩存的資源。

如果服務端提示緩存資源未改動(Not Modified),資源會被重定向到浏覽器緩存,這種情況下網絡請求對應的狀态碼是 304,比如:

【前端 · 面試 】HTTP 總結(九)—— HTTP 協商緩存

規則

協商緩存的整體規則如下所示:

【前端 · 面試 】HTTP 總結(九)—— HTTP 協商緩存

從上圖可以看出,雖然用戶端仍然發起了 HTTP 請求伺服器,但是伺服器隻做了标志對比來确認是否使用緩存,如果确認使用緩存,就不會再傳回具體的資源了。這樣做雖然沒有減少請求數量,但是極大減小了請求負荷,可以明顯提升請求速度和減小網絡帶寬。

上圖是緩存辨別正常有效的時序圖,但其實協商緩存的驗證結果也存在兩種情況:

  • 辨別有效
  • 辨別過期
協商緩存需要配合強緩存使用,使用協商緩存需要先設定 Cache-Control:no-cache 或者 pragma:no-cache 來告訴浏覽器不走強緩存。

【前端 · 面試 】HTTP 總結(九)—— HTTP 協商緩存

屬性

對于協商緩存來說,緩存辨別的傳遞是我們着重需要了解的,它在 Response Header 和 Request Header 之間進行傳遞。

緩存辨別可以分為兩類:

  • Last-Modified 和 If-Modified-Since
  • Etag 和 If-None-Match

我們一般會說,協商緩存的緩存辨別是 Last-Modified(最後修改時間) 和 Etag(标簽或名稱),因為它們兩個都是由服務端确定并傳回的。

浏覽器攜帶的是具有判斷意味的屬性 —— If-Modified-Since(從什麼時間以來是否改變) 和 If-None-Match(是否比對不到)。

緩存辨別的攜帶位置如下圖所示:

【前端 · 面試 】HTTP 總結(九)—— HTTP 協商緩存

在具體的網絡請求中,緩存辨別如下圖所示:

【前端 · 面試 】HTTP 總結(九)—— HTTP 協商緩存

Last-Modified 和 If-Modified-Since 是 HTTP 1.0 引入的。

Last-Modified

當浏覽器第一次通路一個資源的時候,伺服器會在 Response 、Header 中傳回一個 Last-Modified,代表這個資源最後的修改時間。

If-Modified-Since

再次請求伺服器時,請求頭會攜帶此字段,值為上次請求時伺服器傳回的 Last-Modified 的值。

伺服器收到請求後發現有頭 If-Modified-Since 則與被請求資源的最後修改時間進行比對:

  • 若資源的最後修改時間大于 If-Modified-Since,說明資源又被改動過,則響應整片資源内容,傳回狀态碼 200 和最新的資源,響應頭中攜帶最新的緩存辨別 Last-Modified。
  • 若資源的最後修改時間小于或等于 If-Modified-Since,說明資源無新修改,則響應 HTTP 304,告知浏覽器繼續使用所儲存的 cache。

缺陷

使用 Last-Modified 是有一定缺陷的:

  • 如果資源更新的速度是秒以下機關,那麼該緩存是不能被使用的,因為 If-Modified-Since 隻能檢查到以秒為最小計量機關的時間差。
  • 如果檔案是通過伺服器動态生成的,那麼該方法的更新時間永遠是生成的時間,盡管檔案可能沒有變化,是以起不到緩存的作用。
  • 我們編輯了檔案,但檔案的内容沒有改變。服務端并不清楚我們是否真正改變了檔案,它仍然通過最後編輯時間進行判斷。是以這個資源在再次被請求時,會被當做新資源,進而引發一次完整的響應——不該重新請求的時候,也會重新請求。

為了解決上面伺服器沒有正确感覺檔案變化的問題,Etag 作為 Last-Modified 的補充出現了。

Etag 和 If-None-Match 是一對封包頭,屬于HTTP 1.1。

ETag 和 If-None-Match 的值是一串 hash 碼,代表的是一個資源的辨別符,當服務端的檔案變化的時候,它的 hash 碼會随之改變。

Etag

伺服器響應請求時,告訴浏覽器目前資源在伺服器的唯一辨別(生成規則由伺服器決定)。

ETag 又有強弱校驗之分,如果 hash 碼是以 "W/" 開頭的一串字元串,說明此時協商緩存的校驗是弱校驗的,隻有伺服器上的檔案差異(根據 ETag 計算方式來決定)達到能夠觸發 hash 值字尾變化的時候,才會真正地請求資源,否則傳回 304 并加載浏覽器緩存。

If-None-Match

再次請求伺服器時,通過此字段通知伺服器客戶段緩存資料的唯一辨別。

伺服器收到請求後發現有頭 If-None-Match 則與被請求資源的唯一辨別進行比對:

  • 不同,說明資源又被改動過,則響應整片資源内容,傳回狀态碼 200。
  • 相同,說明資源無新修改,則響應 HTTP 304,告知浏覽器繼續使用所儲存的 cache。

Etag 的生成過程需要伺服器額外付出開銷,會影響服務端的性能,這是它的弊端。

是以啟用 Etag 需要我們審時度勢:

  • Etag 并不能替代 Last-Modified,它隻能作為 Last-Modified 的補充和強化存在。
  • Etag 在感覺檔案變化上比 Last-Modified 更加準确,優先級也更高。
  • 當 Etag 和 Last-Modified 同時存在時,以 Etag 為準。

兩種屬性比較

  • 在精确度上,Etag 要優于 Last-Modified,Last-Modified 的時間機關是秒,如果某個檔案在 1 秒内改變了多次,那麼他們的 Last-Modified 其實并沒有展現出來修改,但是 Etag 每次都會改變確定了精度。
  • 在性能上,Etag 要遜于 Last-Modified,畢竟 Last-Modified 隻需要記錄時間,而 Etag 需要伺服器通過算法來計算出一個 hash 值。

    在優先級上,伺服器校驗優先考慮 Etag。

總結

總結一下上面的内容:

  • 協商緩存是依靠緩存辨別來判斷資源是否有效。
  • 緩存辨別包括 Last-Modified(If-Modified-Since)和 Etag(If-None-Match)。
  • 響應頭攜帶的是 Last-Modified 和 Etag。
  • 請求頭攜帶的是 If-Modified-Since 和 If-None-Match。
  • Etag 是 Last-Modified 的補充和完善,并不能完全替代 Last-Modified。
  • Etag 的優先級高于 Last-Modified。
  • Last-Modified 的性能要高于 Etag,但是精确性卻遜色于 Etag。

以上就是 HTTP 協商緩存的相關内容。

~

~本文完,感謝閱讀!

學習有趣的知識,結識有趣的朋友,塑造有趣的靈魂!

繼續閱讀