關於 http cache 的一個小問題以及引起的思考

關於 http cache 的一個小問題以及引起的思考

本文主要介紹在沒有設置強制緩存時的 lm factor 算法,以及關於緩存策略的思考。以及如何使用 service worker 加強緩存。前端

本文地址 shanyue.tech/post/a-prob…web

問題回顧

前幾天,寫了一篇博客,瀏覽器中的二進制,其中總結了一張圖。面試

前端中二進制的轉換

後來,我對圖片作了一些更改,又發佈了上去。這時候問題出現了,圖片沒有更新!算法

比沒有緩存更嚴重的問題是緩存了不應緩存的東西!docker

我研究了下該圖片的 Request/Response 信息,總結以下瀏覽器

  1. 圖片從緩存中取,沒有走網絡流量,顯示 from memory cache
  2. 響應頭設置了 ETag
  3. 響應頭沒有設置 Cache-Control,以及 Expires

如今再來看文章開頭那張圖,若是這是一段面試題,第二次請求圖片資源應該是哪一種緩存策略緩存

LM factor 算法

再拋出一個問題,如何得出某資源的最後更新時間以及本次請求資源所生成的時間服務器

先熟悉如下兩個 Response Header網絡

  • Date
  • Last-Modified

從這兩個頭能夠計算出資源已經多久沒有更新了。frontend

LM factor 算法在沒有 Cache-Control 以及 Expires 的時候,用來計算應該強制緩存多長時間。

算法大體介紹以下,若是本次請求資源,發現沒有關於強制緩存的配置,並且該資源最後一次修改是在 10 小時之前,那麼就對它設置 10 * factor 個小時的緩存。factor 即 LM factor,設置爲 (0, 1)。

問題總結

若是你不設置 Cache-Control 的話,那你的資源很危險,用戶可能正在訪問已過時的資源!

另外,在對你的應用進行二次刷新時,你大部分資源都進了緩存,加載速度很快。先不要高興太早,有可能不是你緩存設置得好,更有多是你壓根就沒設置緩存。

一言蔽之,不管如何,要主動設置 Cache-Control,不要讓瀏覽器替你作決策

問題解決

找到了問題所在,只需添加一個響應頭 Cache-Control: no-cache; 就能夠解決問題。

no-cache 表明須要每次校驗資源的新鮮度,來決定是否從緩存中取 no-store 表明從不存緩存

因爲博客沒有能作長期緩存的資源,統一對博客的全部請求添加了響應頭 Cache-Control: no-cache。我使用了 Traefik 做爲反向代理,修改 docker-compose.yml 以下

version: "3"
services:
 blog:
 build:
 context: .
 restart: always
 labels:
 - "traefik.frontend.rule=Host:blog.xiange.tech"
 - "traefik.frontend.headers.customResponseHeaders=Cache-Control:no-cache"
複製代碼

再次部署後,圖片緩存的問題已經解決。

緩存策略設置

這時再思考一個項目的緩存策略設置

圖片總結以下,參考谷歌開發者文檔 developers.google.com/web/fundame…

如何設置資源的緩存策略

而個人緩存策略簡單總結以下

  • 對於帶指紋信息的資源設置永久緩存
  • 對於不帶指紋信息的資源設置 ETag 每次校驗新鮮度

使用 Service Worker 加強緩存

若是 304 過多怎麼辦

若是不帶指紋的資源過多,又須要資源保障實時的新鮮度如何處理。這麼一大堆資源每次去向服務器比對 ETag,服務器也是很煩的,畢竟也會消耗一些 CPU。

這時候能夠考慮使用 service worker 作緩存加強。

  1. 使用 workbox 自動生成 sw.js
  2. sw.js 對全部資源打一個 hash 戳,維護一個文件與hash的鍵值對清單,並使用 Cache API 對全部資源作永久緩存。
  3. sw.js 每次請求須要校驗新鮮度
  4. 當靜態資源有所更改,sw.js 維護的鍵值對清單發生變化,sw.js 會獲取到新的資源

此時,只須要 sw.js 每次校驗新鮮度,而無需一大堆文件都去校驗新鮮度了

相關文章
相關標籤/搜索