http緩存 cdn緩存

一、ETag

初識HTTP緩存-ETag

第一次請求


第一次請求時候請求參數中並沒有 If-None-Match 字段但是卻有個Pragma;同時在請求的Response中有一個 ETag: W/"a-QFZ79AprHeNlMfPMKXyEUV+lyOg"字段。

第二次請求

 

刷新頁面後再次請求在請求頭中卻有個 If-None-Match: W/"a-QFZ79AprHeNlMfPMKXyEUV+lyOg" ,If-None-Match 的值和第一次請求的ETag的值相同。

也就是說,瀏覽器會根據HTTP請求的ETag驗證請求的資源是否發生了改變,如果它未發生變化,服務器將返回“304 Not Modified”響應,並且資源從瀏覽器緩存中讀取,這樣就不必再次下載請求。

爲了驗證查證的結果,我又添加一個請求處理。這個過程是,客戶端明確返回一個ETag, 但是這裏每次請求的的返回值都不相同,這裏簡單的使用了個etag++。

// app.js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('hello http');
})


// 驗證ETag
let etag = 0;
app.get('/test', (req, res) => {
  etag++;
  res.set('ETag', etag);
  res.send('ETag');
})

app.listen(3000, () => {
  console.log('The server is running at http://127.0.0.1:3000/')
})

查看下 /test 地址的請求結果,會發現If-None-Match 的值和 Response中的 ETag值每次都不相同,並且是 瀏覽器會將每次的 ETag 值都緩存起來在下次請求的時候發送給服務器。這樣一來,每次服務器每次校驗的值都是不相同的,所以這種就沒有做緩存,因此每次請求 /test 地址都是 200 的狀態。

image.png

二、Last-Modified

http響應Last-Modified和ETag
http協議 - 淺談ETag
Etag是在HTTP 1.1中引入的,爲了解決一些Last-Modified無法解決的問題,比如:

  • 一些文件也許會週期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認爲這個文件被修改了,而重新GET;
  • 某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒)
  • 部分服務器不支持精確時間;

爲此,HTTP/1.1引入了Etag(Entity Tags).Etag僅僅是一個和文件相關的標記,可以是一個版本標記,比如說v1.0.0或者說"2e681a-6-5d044840"這麼一串看起來 很神祕的編碼。但是HTTP/1.1 標準並沒有規定Etag的內容是什麼或者說要怎麼實現,唯一規定的是Etag需要放在""內。

ETag和Last-Modified的作用和用法也是差不多,說一說他們的區別。首先在精確度上,Etag要優於Last-Modified。Last-Modified的時間單位是秒,如果某個文件在1秒內改變了多次,那麼他們的Last-Modified其實並沒有體現出來修改,但是Etag每次都會改變確保了精度;如果是負載均衡的服務器,各個服務器生成的Last-Modified也有可能不一致。第二在性能上,Etag要遜於Last-Modified,畢竟Last-Modified只需要記錄時間,而Etag需要服務器通過算法來計算出一個hash值。第三在優先級上,服務器校驗優先考慮Etag。

知乎 關於瀏覽器的緩存,有了Etaglast-Modified 還有必要存在嗎???

三、強緩存和協商緩存

HTTP 緩存機制一二三
一文讀懂前端緩存
HTTP 頭信息控制緩存大致分爲兩種:強緩存和協商緩存。強緩存如果命中緩存不需要和服務器端發生交互,而協商緩存不管是否命中都要和服務器端發生交互,強制緩存的優先級高於協商緩存。

匹配流程(已有緩存的情況下)

 

1.Expires

這是 HTTP 1.0 的字段,表示緩存到期時間,是一個絕對的時間 (當前時間+緩存時間),如Expires: Thu, 10 Nov 2017 08:45:11 GMT。在響應消息頭中,設置這個字段之後,就可以告訴瀏覽器,在未過期之前不需要再次請求。但是,這個字段設置時有兩個缺點:

  • 由於是絕對時間,用戶可能會將客戶端本地的時間進行修改,而導致瀏覽器判斷緩存失效,重新請求該資源。此外,即使不考慮自行修改,時差或者誤差等因素也可能造成客戶端與服務端的時間不一致,致使緩存失效。
  • 寫法太複雜了。表示時間的字符串多個空格,少個字母,都會導致非法屬性從而設置失效。

2.Cache-control

已知Expires的缺點之後,在HTTP/1.1中,增加了一個字段Cache-control,該字段表示資源緩存的最大有效時間,在該時間內,客戶端不需要向服務器發送請求。這兩者的區別就是前者是絕對時間,而後者是相對時間。如下:Cache-control: max-age=2592000。Cache-control 的優先級高於 Expires,爲了兼容 HTTP/1.0 和 HTTP/1.1,實際項目中兩個字段我們都會設置。

Cache-Control 可以由多個字段組合而成,主要有以下幾個取值:

(1)max-age
指定一個時間長度,在這個時間段內緩存是有效的,單位是s。例如設置 Cache-Control:max-age=31536000,也就是說緩存有效期爲(31536000 / 24 / 60 * 60)天,第一次訪問這個資源的時候,服務器端也返回了 Expires 字段,並且過期時間是一年後。

(2)s-maxage
同 max-age,覆蓋 max-age、Expires,但僅適用於共享緩存,在私有緩存中被忽略。

(3)public
表明響應可以被任何對象(發送請求的客戶端、代理服務器等等)緩存。

(4)private
表明響應只能被單個用戶(可能是操作系統用戶、瀏覽器用戶)緩存,是非共享的,不能被代理服務器緩存。

(5)no-cache
強制所有緩存了該響應的用戶,在使用已緩存的數據前,發送帶驗證器的請求到服務器。不是字面意思上的不緩存。

(6)no-store
禁止緩存,每次請求都要向服務器重新獲取數據。

(7)must-revalidate
如果超過了 max-age 的時間,瀏覽器必須向服務器發送請求,驗證資源是否還有效。

這裏有一個疑問:max-age=0 和 no-cache 等價嗎?從規範的字面意思來說,max-age 到期是 應該(SHOULD) 重新驗證,而 no-cache 是 必須(MUST) 重新驗證。但實際情況以瀏覽器實現爲準,大部分情況他們倆的行爲還是一致的。(如果是 max-age=0, must-revalidate 就和 no-cache 等價了)

順帶一提,在 HTTP/1.1 之前,如果想使用 no-cache,通常是使用 Pragma 字段,如 Pragma: no-cache(這也是 Pragma 字段唯一的取值)。但是這個字段只是瀏覽器約定俗成的實現,並沒有確切規範,因此缺乏可靠性。它應該只作爲一個兼容字段出現,在當前的網絡環境下其實用處已經很小。

四、HTTP 緩存實際應用

HTTP 緩存機制一二三
一文讀懂前端緩存

1.首先要明確哪些內容適合被緩存哪些不適合

考慮緩存的內容:

  • css樣式文件
  • js文件
  • logo、圖標
  • html文件
  • 可以下載的內容

一些不應該被緩存的內容:

  • 業務敏感的 GET 請求

2.可緩存的內容又分爲幾種不同的情況

(1)不經常改變的文件
給 max-age 設置一個較大的值,一般設置 max-age=31536000
比如引入的一些第三方文件、打包出來的帶有 hash 後綴 css、js 文件。一般來說文件內容改變了,會更新版本號、hash 值,相當於請求另一個文件。

標準中規定 max-age 的值最大不超過一年,所以設成 max-age=31536000。至於過期內容,緩存區會將一段時間沒有使用的文件刪除掉。

(2)可能經常需要變動的文件:
Cache-Control: no-cache / max-age=0
比如入口 index.html 文件、文件內容改變但名稱不變的資源。選擇 ETag 或 Last-Modified 來做驗證,在使用緩存資源之前一定會去服務器端做驗證,命中緩存時會比第一種情況慢一點點,畢竟還要發請求進行通信。

五、cdn緩存

http緩存與cdn緩存配置指南
閒話 CDN
從HTTP響應頭看各家CDN緩存技術

【CDN學習筆記1】CDN基本概念和原理
【CDN學習筆記2】如何判斷CDN緩存是否生效
【CDN學習筆記3】CDN緩存規則錯誤導致網頁顯示錯誤和預熱失敗的案例
【CDN學習筆記4】CDN緩存刷新與預熱的區別
【CDN學習筆記5】源站IP變更後導致圖片顯示不出來的案例
【CDN學習筆記6】CDN回源到阿里雲主機被拒絕的案例
【CDN學習筆記7】CDN幾種常見的組網方式

Web 緩存大致可以分爲:數據庫緩存、服務器端緩存(代理服務器緩存、CDN 緩存)、瀏覽器緩存。瀏覽器緩存也包含很多內容: HTTP 緩存、indexDB、cookie、localstorage 等等。

cdn緩存是一種服務端緩存,CDN服務商將源站的資源緩存到遍佈全國的高性能加速節點上,當用戶訪問相應的業務資源時,用戶會被調度至最接近的節點最近的節點ip返回給用戶,在web性能優化中,它主要起到了,緩解源站壓力,優化不同用戶的訪問速度與體驗的作用。

1.流程

image.png

 

客戶端訪問網站的過程:沒有CDN:

  • 用戶在瀏覽器訪問欄中輸入要訪問的域名;
  • 瀏覽器向DNS服務器請求對該域名的解析;
  • DNS服務器返回該域名的IP地址給瀏覽器
  • 瀏覽器使用該IP地址向服務器請求內容。
  • 服務器將用戶請求的內容返回給瀏覽器。

使用了CDN:

  • 用戶在瀏覽器中輸入要訪問的域名。
  • 瀏覽器向DNS服務器請求對域名進行解析。由於CDN對域名解析進行了調整,DNS服務器會最終將域名的解析權交給CNAME指向的CDN專用DNS服務器。
  • CDN的DNS服務器將CDN的負載均衡設備IP地址返回給用戶。
  • 用戶向CDN的負載均衡設備發起內容URL訪問請求。
  • CDN負載均衡設備會爲用戶選擇一臺合適的緩存服務器提供服務。選擇的依據包括:根據用戶IP地址,判斷哪一臺服務器距離用戶最近;根據用戶所請求的URL中攜帶的內容名稱,判斷哪一臺服務器上有用戶所需內容;查詢各個服務器的負載情況,判斷哪一臺服務器的負載較小。基於以上這些依據的綜合分析之後,負載均衡設置會把緩存服務器的IP地址返回給用戶。
  • 用戶向緩存服務器發出請求。
  • 緩存服務器響應用戶請求,將用戶所需內容傳送到用戶。如果這臺緩存服務器上並沒有用戶想要的內容,而負載均衡設備依然將它分配給了用戶,那麼這臺服務器就要向它的上一級緩存服務器請求內容,直至追溯到網站的源服務器將內容拉取到本地。

2.緩存規則

在用戶第一次訪問網站後,網站的一些靜態資源如圖片等就會被下載到本地,作爲緩存,當用戶第二次訪問該網站的時候,瀏覽器就會從緩存中加載資源,不用向服務器請求資源,從而提高了網站的訪問速度,而若使用了CDN,當瀏覽器本地緩存的資源過期之後,瀏覽器不是直接向源站點請求資源,而是向CDN邊緣節點請求資源,CDN邊緣節點中也存在緩存,若CDN中的緩存也過期,那就由CDN邊緣節點向源站點發出回源請求來獲取最新資源。

CDN節點緩存機制在不同服務商中是不同的,但一般都遵循HTTP協議,通過http響應頭中的Cache-Control:max-age的字段來設置CDN節點文件緩存時間。當客戶端向CDN節點請求數據時,CDN會判斷緩存數據是否過期,若沒有過期,則直接將緩存數據返回給客戶端,否則就向源站點發出請求,從源站點拉取最新數據,更新本地緩存,並將最新數據返回給客戶端。CDN服務商一般會提供基於文件後綴、目錄多個維度來指定CDN緩存時間,爲用戶提供更精細化的緩存管理。CDN緩存時間會對“回源率”產生直接的影響,若CDN緩存時間短,則數據經常失效,導致頻繁回源,增加了源站的負載,同時也增大了訪問延時;若緩存時間長,數據更新時間慢,因此需要針對不同的業務需求來選擇特定的數據緩存管理。

以騰訊雲舉例,打開cdn加速服務配置,面板如下。

 

image.png

 

可以看到,提供給我們的配置項只有文件類型(或文件目錄)和刷新時間,意義也很簡單,針對不同文件類型,在cdn節點上緩存對應的時間。

六、推薦閱讀 知乎 大公司裏怎樣開發和部署前端代碼?

大公司的靜態資源優化方案,基本上要實現這麼幾個東西:

  • 配置超長時間的本地緩存 —— 節省帶寬,提高性能
  • 採用內容摘要作爲緩存更新依據 —— 精確的緩存控制
  • 靜態資源CDN部署 —— 優化網絡請求
  • 更資源發佈路徑實現非覆蓋式發佈 —— 平滑升級

 

發佈了96 篇原創文章 · 獲贊 34 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章