整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          淺談HTTP緩存與CDN緩存的那點事

          淺談HTTP緩存與CDN緩存的那點事

          TTP緩存與CDN緩存一直是提升web性能的兩大利器,合理的緩存配置可以降低帶寬成本、減輕服務器壓力、提升用戶的體驗。而不合理的緩存配置會導致資源界面無法及時更新,從而引發一系列的衍生問題。本文將分別將從HTTP緩存與cdn緩存的規則、流程、配置入手,能讓大家了解基礎概念的同時,可對自己的項目配置定制化的緩存調優方案,以及在遇到緩存問題時如何快速定位解決。


          首先,讓我們來了解一下緩存在實際場景中的應用

          用戶第一次訪問網站時,瀏覽器會從服務器獲取所有的資源。在傳輸過程中,瀏覽器會通過一些約定好的響應頭,從而確定是否需要將這個資源保存一份到本地作為緩存,當用戶第二次訪問該網站的時候,瀏覽器就會從緩存中加載資源,不用向服務器請求資源,從而提高了網站的訪問速度,而若使用了CDN,當瀏覽器本地緩存的資源過期之后,瀏覽器不是直接向源站點請求資源,而是向CDN邊緣節點請求資源,CDN邊緣節點中也存在緩存,若CDN中的緩存也過期,那就由CDN邊緣節點向源站點發出回源請求來獲取最新資源。

          HTTP緩存

          簡介

          http緩存是一種客戶端緩存,當Web瀏覽器向服務器發起資源請求時,服務器可以在響應報文頭中包含緩存相關的信息。這些HTTP Header會告訴瀏覽器是否以及如何緩存資源,再次請求時如果命中緩存將直接讀取本地緩存不再發出請求。

          緩存規則

          http緩存規則由響應頭中ExpiresCache-ControlLast-ModifiedEtag 這四個關鍵字段控制。其中ExpiresCache-Control為強緩存用來確定確定緩存的存儲時間,Last-ModifiedEtag為協商緩存則用來確定緩存是否要被更新,接下來我們簡單來看一下區別。

          強緩存

          ?expires: HTTP1.0中用來控制緩存時間的參數,header里包含日期/時間,用GMT格式的字符串表示, 即在此時間之后,響應過期。

          ?cache-control: HTTP1.1中用來控制緩存時間的參數

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

          ?private: 表明響應只能被單個用戶緩存,不能作為共享緩存(即代理服務器例如CDN不能緩存它)。

          ?max-age=<seconds>: 設置緩存存儲的最大周期,相對于請求的時間緩存seconds秒,在此時間內,訪問資源直接讀取本地緩存,不向服務器發出請求。(與expires同時出現時,max-age優先級更高)

          ?s-maxage=<seconds>: 規則等同max-age,覆蓋max-age 或者 Expires 頭,但是僅適用于共享緩存(比如各個代理),并且私有緩存中它被忽略。(與expires或max-age同時出現時,s-maxage優先級更高)

          ?no-store: 不緩存服務器響應的任何內容,每次訪問資源都需要服務器完整響應

          ?no-cache: 緩存資源,但立即過期,每次請求都需要跟服務器對比驗證資源是否被修改。(等同于max-age=0)

          協商緩存

          ?Last-modified: 源頭服務器認定的資源做出修改的日期及時間。精確度比Etag低。包含有If-Modified-Since ( 資源修改的時間 )或 If-Unmodified-Since首部的條件請求會使用這個字段,Last-Modified優先級低于Etag。

          ?Etag: HTTP響應頭是資源的特定版本的標識符,如果客戶端想再次請求相同的URL,將會發送一個包含已保存的ETag和“If-None-Match”(標識符字符串)字段的請求。客戶端請求之后,服務器可能會比較客戶端的ETag和當前版本資源的ETag(只要文件內容改動,ETag就會重新計算)。如果ETag值匹配,這就意味著資源沒有改變,服務器便會發送回一個極短的響應,包含HTTP “304 未修改”的狀態。304狀態告訴客戶端,它的緩存版本是最新的,并應該使用它。

          我們通過chrome控制臺可以很輕松的找到一個案例:

          ??圖中配置

          1.Cache-control: max-age=3600代表相對于請求時間,緩存3600秒,即1小時,在此時間內,再次訪問資源直接讀取本地緩存,不向服務器發送請求.

          2.Last-modified: Mon...上次修改時間,如果緩存時間過期,該字段將用于與請求中的If-Modified-Since字段進行對比,一致則繼續使用之前緩存,不一致則認定緩存失效

          3.Expires: 在http1.0版本下被cache-control覆蓋,此處意為緩存至Mon, 07 Nov ...

          4.Etag: Web服務器會返回資源和其相應的ETag值,該字段將用于與當前客戶端版本資源的ETag進行對比,一致則繼續使用之前緩存,不一致則認定緩存失效

          緩存流程


          ??緩存規則在其中是如何起作用的呢,我們來看幾個重點關注部分

          重點關注1: 緩存是否過期

          基于該資源上次響應緩存規則同時滿足下列條件則視為緩存未過期,不發請求直接從本地緩存讀取該文件。需要注意的是,判斷緩存是否過期只跟客戶端有關系,與服務端無關。1&2&3同時滿足即認為緩存未過期,相反則是已過期

          1.cache-control值為max-age

          2.max-age > 0

          3.當前 date < 上次請求時的date + max-age

          注:如果HTTP為1.0時,則用expires判斷是否過期,如果HTTP為1.1及其以上時,則查看cache-control。

          重點關注2: 詢問服務器資源是否修改

          判斷資源是否修改,需要客戶端與服務器共同協作,客戶端在首次拿到資源緩存后會存儲Etag(若有)和Last-Modified(若有),在下次緩存過期時會將Etag寫在請求頭部中的If-None-Match中,將Last-Modified值寫在請求頭部中的If-Modified-Since中,服務端優先對Etag進行對比,然后再對比Last-Modified,一致即視為緩存沒有修改,命中協商緩存,返回304,不一致則返回新文件并帶上新的Etag或Last-Modified值。

          重點關注3: 緩存規則

          參考上文緩存規則,不在贅述。


          小結

          對于http緩存的配置,我們只有在了解http緩存的原理、規則、流程后,才能根據不同的情況定制不同的規則,真正的發揮http緩存在實際業務中的價值。


          CDN緩存

          cdn緩存是一種服務端緩存,cdn服務商可以將源站上的資源緩到其各地的邊緣服務器節點上。當用戶訪問該資源時,cdn再通過負載均衡將用戶的請求調度到最近的緩存節點上,有效減少了鏈路回源,提高了資源訪問效率及可用性,降低帶寬消耗

          緩存規則

          與http緩存規則不同的是,這個規則并不是規范性的,而是由cdn服務商來制定,我們以JD內部CDN舉例,打開cdn接入界面,面板如下。

          ??
          可以看到,提供給我們的配置項只有文件類型(或文件目錄)和Http2,在cdn節點上緩存默認遵循源站設置緩存時長。

          運作流程

          ??由圖我們可以看出CDN的主要處理邏輯集中在緩存處理階段,除了關注CDN緩存的文件類型及時間外,我們還需要引入一個概念——回源,客戶端請求訪問資源時,如果CDN節點上未緩存該資源,或者部署預熱任務給CDN節點時,CDN節點會回源站獲取資源。如圖中所示,接入cdn后,我們提供服務的服務器就是源站,源站一般情況下只會在cdn節點沒有資源或cdn資源失效時接收到cdn節點的資源請求,其他時間,源站并不會接收請求。簡單的概括就是,沒有資源就去源站讀取,有資源就直接發送給用戶。值得注意的是cdn中有s-maxage=0、max-age=0、no-cache、no-store、private中的任一種時候,該類型文件就被認定為不緩存文件,就是所有請求直接轉發源站,只有當緩存時間大于0且緩存過期的時候,才會與源站對比緩存是否被修改。

          緩存配置

          與在Web瀏覽器中的緩存規則類似,可通過發送緩存指令標頭來控制緩存在CDN中的執行方式。盡管大部分標頭最初都旨在解決客戶端瀏覽器中的緩存問題,但現在所有中間緩存(如 CDN)也會使用這些標頭,可使用兩個標頭來定義緩存刷新:Cache-Control 和 Expires。 如果兩者都存在,則 Cache-Control 為最新且優先于 Expires。 還有兩種用于驗證的標頭類型(稱為驗證程序):ETag 和 Last-Modified。 如果兩者均已定義,則 ETag 為最新且優先于 Last-Modified。以OSS對象存儲為例,在緩存配置的文檔中特別有以下說明。

          緩存繼承

          當用戶請求您某一業務資源時,源站對應的Response HTTP Header中存在Cache-Control字段,此時默認策略如下:

          ?Cache-Control字段為max-age,對該資源的緩存時間以配置的緩存時間為主,對于小于1小時的緩存時長,不繼承max-age指定時間。

          ?Cache-Control字段為s-maxage=0、max-age=0、no-cache、no-store、private、nil或無 Cache-Control字段時,對象存儲會源節點會為CDN默認添加:Cache-Control: max-age=3600頭部字段,已確保提高緩存的命中率,同時應對高并發回源流量帶來的風險與成本的增加。

          緩存影響

          1.如果http緩存設置cache-control: max-age=600,即緩存10分鐘,但對象存儲cdn緩存配置中設置文件緩存時間默認為1小時,那么就會出現如下情況,文件被訪問后第20分鐘修改并上傳到服務器,用戶重新訪問資源,響應碼會是304,對比緩存未修改,資源依然是舊的,一個小時后再次訪問才能更新為最新資源

          2.如果不設置cache-control呢,在http緩存中我們說過,如果不設置cache-control,那么會有默認的緩存時間,但在這里,對象存儲cdn服務商明確會在沒有cache-control字段時主動幫我們添加cache-control: max-age=3600。

          注:針對問題1,也并非沒有辦法,當我們必須要在緩存期內修改文件,并且不向想影響用戶體驗,那么我們可以使用cdn服務商提供的強制更新緩存功能,主要注意的是,這里的強制更新是更新服務端緩存,http緩存依然按照http頭部規則進行自己的緩存處理,并不會受到影響。

          小結

          cdn緩存的配置并不復雜, 復雜的情況在于cdn緩存配置會受到http緩存配置的影響,并且不同的cdn運營商有各自的運營規則計費標準,結合來看才能讓cdn緩存在業務中發揮最大的效能。

          HTTP緩存與CDN緩存的結合

          在我們分別了解http緩存配置和cdn緩存配置后,讓我們再結合引言看一次二者結合的請求過程

          ??當用戶訪問我們的業務服務器時,首先進行的就是http緩存處理,如果http緩存通過校驗,則直接響應給用戶,如果未通過校驗,則繼續進行cdn緩存的處理,cdn緩存處理完成后返回給客戶端,由客戶端進行http緩存規則存儲并響應給用戶。再回到開篇緩存在實際場景中的應用,當我們分析緩存問題時,一定要將兩個流程獨立開來分析判斷,是由于http緩存配置的不合理,還是cdn緩存未及時更新引起的問題。


          實戰場景推薦(懶人版)

          不同訪問場景下的緩存規則選擇

          1.不更新文件內容

          優先使用http的本地緩存,配置cache-control: max-age=seconds //seconds > 0(且設置為較大值31536000,即1年):強緩存,緩存當前資源,在配置時期內,再次請求資源直接讀取本地緩存。

          使用cdn緩存,當本地緩存無法使用時,配置較大的cache-control:同樣可以讓業務直接訪問cdn資源,且配置時間內不會再發生回源請求。

          2.很少更新文件內容

          對于img,css,js,fonts等非html資源,我們可以直接考慮配置cache-control: max-age=seconds //seconds > 0,并且max-age配置的時間可以相對久一些,類似于緩存規則案例中,cache-control: max-age=36000配置10小時的緩存,需要注意的是,這樣配置并不代表這些資源就一定十小時不變,其根本原因在于目前前端構建工具在靜態資源中都會加入戳的概念(例如,webpack中的[hash],gulp中的gulp-rev),每次修改均會改變文件名或增加query參數,本質上改變了請求的地址,也就不存在緩存更新的問題。

          3.頻繁更新文件內容

          對于html資源,作為前端資源的入口文件,一旦被強緩存,那么相關的js,css,img等均無法更新。對于高頻維護的業務類項目,建議配置cache-control: no-cache或cache-control: max-age=0:采用協商緩存,緩存當前資源,但每次訪問都需要跟服務器對比,檢查資源是否被修改。但是基于流量和成本的考慮更推薦于max-age設置一個較小值,例如3600,一小時過期。對于一些活動項目,上線后不會進行較大改動,建議業務配置一個較小的max-age值,否則一旦出現bug或是未知問題,用戶無法及時更新。

          除了以上考慮,有時候其他因素也會影響緩存的配置,例如春晚紅包除夕活動,高并發大流量很容易給服務器帶來極大挑戰,這時我們作為前端開發,就可以采用靜態頁面提前加載兜底來避免用戶多次進入帶來的流量壓力。


          如何減少緩存規則帶來的訪問影響

          1.通過清理緩存控制

          我們可以使用cdn服務商提供的強制更新緩存功能,主要注意的是,這里的強制更新是更新服務端緩存,http緩存依然按照http頭部規則進行自己的緩存處理,并不會受到影響。

          2.通過url帶版本號或者版本發布時間

          我們在使用對象存儲發布資源時,可根據版本號或發布時間定義url,以作為區分。

          例:https://storage.jd.com/xxx/xx?verson=1.1.1

          例: https://storage.jd.com/xxx/xx?verson=20221111


          線上禁止的訪問策略

          對于訪問同一資源,url帶時間戳、uuid等具有唯一性參數會直接回源至后端服務,帶來極高的帶寬成本及擊穿底層服務的風險,業務在使用CDN域名訪問時,請務必謹慎使用帶有時間戳、唯一性參數的url。


          總結

          技術行業發展到今天,海量的流量已然成為常態,而http緩存和cdn緩存分別作為客戶端緩存和服務端緩存基石更是值得我們去深入學習、思考。

          作者:管宸昊

          介:為了進一步提升網站的訪問速度,我們會使用 CDN 對網站進行加速,但是最近在調試阿里云的函數計算和 CDN 的配合使用時發現了一個需要額外注意的地方。

          作者:鄧超 | Serverless Devs 開源貢獻者

          前言

          為了進一步提升網站的訪問速度,我們會使用 CDN 對網站進行加速,但是最近在調試阿里云的函數計算和 CDN 的配合使用時發現了一個需要額外注意的地方。

          如何使用 CDN 對部署在函數計算上的靜態網站進行緩存

          那么以我部署在函數計算上的博客站[1]為例,逐步地向大家介紹如何使用 CDN 對函數計算托管的靜態網站進行緩存。

          為函數添加 CDN 功能

          1)為函數分配域名并添加 CNAME 記錄

          由于我希望最終用戶能通過 blog.dengchao.fun 來進行訪問,因此需要給函數分配一個不同的域名 blog.xxx.dengchao.fun:

          ?2) 添加自定義域名并設置路由

          將分配的域名設置到函數計算的自定義域名功能中:

          ?因為 CDN 上也可以設置 HTTPs,而且函數計算之前不能設置 SSL 協議版本,因此這里沒有開啟 HTTPS 功能。

          3) 添加源站類型為 "函數計算域名" 的 CDN

          接下來到 CDN 控制臺上新建一個加速域名:

          ?用戶最終將通過加速域名 blog.dengchao.fun 來訪問我的博客站。業務類型選項不會影響最終的加速效果,可以任意選。

          然后添加一個源站:

          ?由于函數計算的自定義域名沒有開啟 HTTPS,所以源站的端口需要設置為 80 端口,同時也可以減少回源時的響應時間 (實際效果微不足道)。

          4) 添加 CNAME 類型的 CDN 加速域名記錄

          設置完源站信息并保存后,阿里云會對源站內容進行審核,審核通過的話就會提供一個 CDN 服務供應商的域名給你:

          ?接下來你需要將你的加速域名解析到 CDN 服務商提供的域名上:

          ?添加好 CNAME 記錄后,CDN 控制臺上過一會兒就會顯示為 "已配置" 狀態,然后你就可以使用配置好的加速域名進行訪問了。

          設置 CDN 緩存

          光配置好加速域名還不夠,不然用戶每次訪問加速域名都需要從源站拉取數據,因此我們需要在 CDN 上設置一下緩存,減少回源次數。

          1)添加緩存過期時間規則

          假設我們希望 CDN 節點能夠對網站根目錄下的所有內容都緩存 1 天,那么我們需要在 CDN 加速域名的緩存管理頁添加對應的配置:

          ?本來操作到這里的時候我就以為緩存設置好了,但網站運行了一段時間后觀察 CDN 的監控卻發現緩存命中率一直很低。通過觀察瀏覽器控制臺里的網絡請求日志,逐個請求頭進行分析,最終發現了一點異常:源站將 Cache-Control 響應頭設置為了 public,max-age=0 。

          2) 修復 Cache-Control 響應頭

          仔細查看了 MDN 上對于 Cache-Control 響應頭的文檔[2],以及阿里云 CDN 對于緩存過期時間配置的介紹[3] 后,確認了之前的 CDN 緩存配置存在缺陷。(典型的不看文檔吃大虧)

          定位好問題以后,解決思路也很清晰了:想辦法刪掉源站的 Cache-Control 響應頭就好了。

          方案一:修改源站 HTTP 服務器返回的 Cache-Control 響應頭

          既然源站的 HTTP 服務器將 Cache-Control 響應頭設置成了 max-age=0 ,那我們把源站的 HTTP 服務器改一下不就好了。

          但考慮到我們部署在函數計算上的靜態網站是由 website-fc 插件生成的 Express 服務器進行托管的,如果修改的話,需要從本地的 website-fc 插件源碼入手進行調整,但 website-fc 插件可能不定期更新, 那我們就需要不定期的進行檢查,視情況重新打補丁,執行起來很費力。因此我們不能選用這個方案。

          方案二:配置 CDN,刪除源站 HTTP 服務器返回的 Cache-Control 響應頭

          再次查看文檔發現阿里云 CDN 提供了 配置回源 HTTP 響應頭[4]的功能,其中包含了刪除回源響應頭的功能。因此我們可以借助這個功能,讓 CDN 刪除掉源站返回的 Cache-Control 響應頭。

          ?配置好以后, 再次觀察加速域名下網絡請求的響應頭,發現確實沒有 Cache-Control:public,max-age=0 的響應頭了。

          3)效果對比

          由于博客站的訪問量并不高,效果不明顯 (簡直看不出來)。因此截取了另一個訪問量相對較大的網站的監控截圖:

          首先是訪問量對比,從監控數據來看近兩天沒有顯著的訪問量差異:

          ?然后是回源流量對比, 發現刪除 Cache-Control 響應頭以后回源流量顯著下降

          ?同時字節命中率與請求命中率都有顯著的提升:

          ?看來我們配置的緩存確實生效了。

          總結

          配置好 CDN 加速域名和緩存過期時間規則以后,記得檢查源站的響應頭。如果源站的響應中已有緩存控制相關的響應頭,那么視情況在源站的 HTTP 服務器上或 CDN 上進行調整。

          另外,多看看文檔。

          參考鏈接:

          [1] 博客站

          https://blog.dengchao.fun/

          [2] MDN 上對于 Cache-Control 響應頭的文檔

          https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control

          [3] 阿里云 CDN 對于緩存過期時間配置的介紹

          https://help.aliyun.com/document_detail/27136.html#title-p27-252-g92

          [4] 配置回源 HTTP 響應頭

          https://help.aliyun.com/document_detail/155769.html

          [5] 阿里云 函數計算

          https://help.aliyun.com/product/50980.html

          [6] 阿里云 CDN

          https://help.aliyun.com/document_detail/27101.html

          [7] 加速原理

          https://help.aliyun.com/document_detail/27101.html#title-sbn-geq-2ez

          [8] 配置回源 HTTP 響應頭

          https://help.aliyun.com/document_detail/155769.html

          [9] 什么是緩存

          https://help.aliyun.com/document_detail/122553.html

          [10] 配置緩存過期時間

          https://help.aliyun.com/document_detail/27136.html

          [11] 緩存規則與優先級

          https://help.aliyun.com/document_detail/27136.html#title-p27-252-g92

          [12] 什么是 Cache Control 響應頭

          https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control

          原文鏈接:http://click.aliyun.com/m/1000342593/

          本文為阿里云原創內容,未經允許不得轉載。

          迎關注頭條號:老顧聊技術

          精品原創技術分享,知識的組裝工


          目錄

          1. 前言
          2. CacheControl響應頭
          3. 邏輯流程圖
          4. ETag驗證
          5. Last-Modified驗證
          6. 請求流程圖
          7. 瀏覽器刷新方式
          8. 動態數據
          9. CDN自定義緩存策略
          10. 總結

          前言

          上一篇互聯網架構重要組員CDN,很多高級開發都沒有實操過,來看這里


          主站蜘蛛池模板: 色久综合网精品一区二区| 日本不卡在线一区二区三区视频 | 国内精品视频一区二区八戒| 日韩好片一区二区在线看| 蜜臀AV在线播放一区二区三区| 日韩一区精品视频一区二区| 国产成人一区二区三区电影网站| 国产美女口爆吞精一区二区| 亚洲AV无码一区二区三区DV| 日韩美女视频一区| 少妇激情AV一区二区三区| 国产成人免费一区二区三区| 97se色综合一区二区二区| 国产在线精品一区免费香蕉| 日韩美一区二区三区| 无码人妻精品一区二区三区蜜桃 | 在线精品自拍亚洲第一区| 国产一区二区三区在线视頻 | 在线观看中文字幕一区| 国产成人无码一区二区在线播放| 欧美成人aaa片一区国产精品| 国产精品丝袜一区二区三区 | 精品国产亚洲一区二区三区| 国产一区二区三区四| 日韩精品一区二区三区毛片| 亚洲一区二区三区深夜天堂| 亚洲福利秒拍一区二区| 日韩一区二区在线播放| 精产国品一区二区三产区| 国内精品一区二区三区最新| 国产午夜精品一区二区三区极品| 无码人妻一区二区三区免费| 韩国资源视频一区二区三区| 色一情一乱一伦一区二区三区日本| 无码少妇一区二区三区| 天堂国产一区二区三区| 久久99精品免费一区二区| 冲田杏梨高清无一区二区| 亚洲福利视频一区二区| 国产精品男男视频一区二区三区| 在线精品国产一区二区三区|