日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

http缓存小记

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 http缓存小记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

緩存的重要性

  • 緩存一般針對不經常進行更新的靜態資源
  • 緩存的原理是在首次請求之后保存一份請求資源的響應副本,當用戶再次發起相同的請求后,如果判斷緩存命中則攔截請求,將之前存儲的響應副本返回給用戶,從而避免重新向服務器發起資源請求
  • 緩存的技術種類有很多,例如代理緩存、瀏覽器緩存、網關緩存、負載均衡及內容分發網絡等,它們大致可分為兩類:共享緩存和私有緩存,共享緩存指緩存的內容可以被多個用戶使用,如公司架設的web代理,私有緩存是指只能單獨被用戶使用的緩存,如瀏覽器緩存
  • http緩存是前端開發中最常接觸的緩存機制之一,它可細分為強制緩存和協商緩存,兩者最大的區別在于緩存命中時,瀏覽器是否需要向服務器端進行詢問以協商緩存的相關信息,進而判斷是否需要就響應內容進行重新請求

強制緩存

對于強制緩存而言如果瀏覽器判斷所請求的目標資源有效命中,則可直接從強制緩存中返回請求響應,無需與服務器進行任何通信

在介紹強制緩存命中之前我們首先看一段響應頭信息

access-control-allow-origin: * age: 734978 content-length: 40830 content-type: image/jpeg cache-control: max-age=31536000 expires: Web, 14 Fed 2021 12:23:42 GMT
  • expires: http1.0中用來控制緩存失效日期的時間戳字段,它由服務端指定后通過響應頭告知瀏覽器,瀏覽器接收到帶有該字段的響應體后進行緩存,若之后的瀏覽器再次發起相同資源請求,便會對比expires與本地當前時間戳,只有當本地時間大于expires時間之后才會允許重新向服務器再次發起請求,否則一直使用的都是緩存,但是這種方式有很大漏洞,就是當本地時間不準確時候,判斷也自然不準確。
  • cache-control:為了解決expires的局限性,從http 1.1開始新增了此字段對expires的功能進行擴展和完善,從上述代碼中可看到cache-control設置了 max-age=31536000的屬性來控制響應資源的有效期,它是一個以秒為單位的時間長度,表示資源在請求到之后的31536000秒內有效
  • cache-control的參數:
    • no-cache:強制進行協商緩存
    • no-store: 禁止使用任何緩存策略,客戶端每次請求都需要服務端給予最新的響應,與no-cache互斥,不能同時設置
    • public: 表示響應資源既可以被瀏覽器緩存,也可被代理服務器緩存
    • private: 限制了響應資源只能被瀏覽器緩存,如果未顯示指定public和private默認值為private
    • max-age: 表示服務器端告知客服端瀏覽器響應資源的過期時常
    • s-maxage: 表示緩存在代理服務器上面的時效,只有當設置了public的時候才能使用

    協商緩存

    • 協商緩存就是在使用本地緩存之前需要向服務器端發起一次GET請求,與之協商當前瀏覽器保存的本地緩存是否已經過期

    協商緩存方法一

  • 在后臺設置響應頭last-modified 為文件的最新一次修改時間,且必須在響應頭上添加cache-control: no-cache,否則無效
  • 當前端接收到帶有last-modified的響應的時候,再次發送請求會在請求頭上自動帶上if-modified-since的字段,這個字段的值就是服務端響應頭中的last-modified的值。然后會有一個去服務端跟最新的資源更新時間也就是last-modified字段做對比,如果相同,服務端應該返回一個304的響應且不返回該資源,如果不相同說明資源更新了,返回200響應并返回最新資源
  • 此方法存在的問題
  • 如果文件資源只是進行了編輯,但內容無變化,但是最新一次修改的時間戳也會更新,會造成不必要的網絡請求資源的浪費
  • 最新一次修改的時間戳單位是秒,如果文件修改的很快在幾百毫秒之內修改完成了,也是無法識別出來是否更新的,最新一次修改時間無變化
  • 協商緩存方法二

    • 為了彌補時間戳方式的不足,在http1.1規范中新增了一個ETag的頭信息,即實體標簽,其內容主要是服務器為不同資源進行哈希運算所生成的一個字符串,該字符串類似文件指紋,只要文件內容編碼存在差異,對應的ETag標簽值就會不同,因此可以使用ETag對文件資源進行更精準的變化感知
    • 步驟如下
    • 服務端根據對應的資源生成一個對應的唯一值,然后當客戶端首次請求這個資源的時候,把這個資源對應的唯一值放在響應頭的ETag字段中返回,注意,同時必須在響應頭上添加cache-control: no-cache,否則無效
    • 客戶端首次接收到資源之后,如果后續再請求相同資源,客戶端請求頭中會自動攜帶if-None-Match的字段,此字段對應第一次請求資源響應頭中的ETag字段
    • 服務端判斷當前資源的if-None-Match字段是否與ETag字段相同,如果相同返回304,如果不同返回200和最新的資源
      • 此方法存在的一些問題
      • 服務器端對生成文件資源的ETag需要付出額外的計算開銷,如果資源尺寸較大且修改較為頻繁,那么生成ETag的過程會影響服務器性能
      • ETag分為強驗證和弱驗證,強驗證根據資源內容生成,保證每個字節都相同,弱驗證根據資源部分屬性值生成,但無法保證每個字節都相同,且在服務器集群的場景下,也會因為不夠準確而降低協商緩存有效性驗證的成功率,所以應該根據具體的資源使用場景來選擇恰當的緩存校驗方式

      緩存決策及注意事項

      • 緩存決策樹

      • 緩存決策示例子
        在使用緩存技術優化性能體驗的過程中,有一個問題是不可逾越的:我們既希望緩存能在客戶端盡可能久的保存,又希望它能在資源發生修改時進行及時更新。

        這是兩個互斥的優化訴求,使用強制緩存并定義足夠長的過期時間就能讓緩存在客戶端長期駐留,但由于強制緩存的優先級高于協商緩存,所以很難進行及時更新;若使用協商緩存,雖然能夠保證及時更新,但頻繁與服務器進行協商驗證的響應速度肯定不及使用強制緩存快。那么如何兼顧二者的優勢呢?

        我們可以將一個網站所需要的資源按照不同類型去拆解,為不同類型的資源制定相應的緩存策略,以下面的HTML文件資源為例

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>HTTP 緩存策略</title><link rel="stylesheet" href="style.css"> </head> <body><img src="photo.jpg" alt="poto"><script src="script.js"></script> </body> </html>
    • 該 HTML 文件中包含了一個 JavaScript 文件 script.js、一個樣式表文件 style.css 和一個圖片文件 photo.jpg,若要展示出該 HTML 中的內容就需要加載出其包含的所有外鏈文件。據此我們可針對它們進行如下設置。

    • 首先HTMl在這里屬于包含其他文件的主文件,為了保證當其中內容發生改變時候能及時的更新,應當將其設置為協商緩存。即為cache-control 字段添加為 no-cache 屬性值,其次是圖片文件,因為網站對圖片的修改基本都是更換修改,同時考慮到圖片文件的數量以及大小可能對客戶端緩存造成不小的開銷,所以可以采用強制緩存,且時間不宜過長,故可以設置cache-contorl 字段值為 max-age= 86400 (24小時)

    • 接下來需要考慮的是樣式表文件 style.css,由于其屬于文本文件,可能存在內容的不定期修改,又想使用強制緩存來提高重用效率,故可以考慮在樣式表文件的命名中增加文件指紋或版本號(比如添加文件指紋后的樣式表文件名變為了 style.51ab84.css ),這樣當發生文件修改后,不同的文件便會有不同的文件指紋,即需要請求的文件 URL 不同了,因此必然會發生對資源的重新請求。同時考慮到網絡中瀏覽器與 CDN 等中間代理的緩存,其過期時間可適當延長到一年,即 cache-control:max-age=3156000

    • 最后是 JavaScript 腳本文件,其可類似于樣式表文件的設置,采取文件指紋和較長的過期時間,如果 JavaScript 中包含了用戶的私人信息而不想讓中間代理緩存,則可為 cache-control 添加 private

    • 從這個緩存策略的示例中我們可以看出,對不同資源進行組合使用強制緩存、協商緩存及文件指紋或版本號,可以做到一舉多得:及時修改更新、較長緩存過期時間及控制所能進行緩存的位置。

    緩存設置的注意事項

    在前面的內容中雖然給出了一種制定緩存決策的思路與示例,但需要明白的一點是:不存在適用于所有場景下的最佳緩存策略。凡是恰當的緩存策略都需要根據具體場景下的請求資源類型、數據更新要求及網絡通信模式等多方面因素考量后制定出來,所以下面列舉一些緩存決策時的注意事項,來作為決策思路的補充。

  • 拆分源碼,分包加載
    對大型的前端應用迭代開發來說,其代碼量通常很大,如果發生修改的部分集中在幾個重要模塊中,那么進行全量的代碼更新顯然會比較冗余,因此我們可以考慮在代碼構建過程中,按照模塊拆分將其打包成多個單獨的文件。這樣在每次修改后的更新提取時,僅需拉取發生修改的模塊代碼包,從而大大降低了需要下載的內容大小。

  • 預估資源的緩存實效
    根據不同資源的不同需求特點,規劃相應的緩存更新時效,為強制緩存指定合適的 max-age 取值,為協商緩存提供驗證更新的 Etag 實體標簽

  • 控制中間代理的緩存
    凡是涉及用戶隱私信息的盡量避免中間代理的緩存,如果對所有用戶響應相同的資源,則可以考慮中間代理也進行緩存。

  • 避免網站的冗余
    緩存是根據請求資源的 URL 進行的,不同的資源會有不同的 URL ,所以盡量不要將相同的資源設置為不同的 URL。

  • 規劃緩存的層次結構
    參考緩存決策中介紹的示例,不僅是請求的資源類型,文件資源的層次結構也會對制定緩存策略有一定影響,我們應當綜合考慮。

  • 緩存是限定域名的

    • 根域下的緩存是共享的。比如 a.com、foo.a.com、bar.a.com 的根域都是 a.com,他們是共享緩存;
    • 同理,域名不同的緩存不共享。比如 a.com、b.com、c.com,他們之間即使加載相同資源也僅在該域名下有效,不共享。

    CDN緩存

    • CDN即內容分發網絡,它是構建在現有網絡基礎上的虛擬智能網絡,依靠部署在各地的邊緣服務器,通過中心平臺的負載均衡、調度及內容分發等功能模塊,使用戶在請求所需訪問的內容時能夠就近獲取,以此來降低網絡堵塞,提高資源對用戶的響應速度。
    • 如果未使用 CDN 網絡進行緩存加速,那么通過瀏覽器訪問網站獲取資源的大致過程如圖所示

    • 請求的步驟大致可分為四步。
  • 當用戶在瀏覽器中輸入所要訪問的域名時,若本機無法完成域名解析工作,則會轉向 DNS 服務器請求對該域名的解析
  • DNS 服務器解析完成返回給瀏覽器該域名所對應的 IP 地址
  • 瀏覽器向該 IP 地址指向服務器發起資源請求
  • 最好服務器響應用戶請求將資源返回給瀏覽器
    • 如果使用 CDN 網絡,則資源獲取的大致過程是這樣。

    • 由于 DNS 服務器將對 CDN 的域名解析交給 CNAME 指向的專用 DNS 服務器,所以對用戶輸入域名的解析最終是在 CDN 專用的 DNS 服務器上完成的。
      解析出的結果 IP 地址并非確定的 CDN 緩存服務器地址,而是 CDN 的負載均衡的地址。
      瀏覽器會重新向該負載均衡服務器發起請求,經過對用戶 IP 地址的距離,所請求資源內容的位置以及各個服務器負載狀況的綜合計算,返回給用戶確定的緩存服務器級地址。
      對目標緩存服務器請求所以資源的過程

      • 當前這個過程也可能會發生所需資源未找到的情況,那么此時便會依次向上一級緩存服務器繼續請求查詢,直至追溯網站的跟服務器并將資源拉到本地,如圖所示

      • 雖然這個過程看起來稍微復雜了一些,但對用戶體驗來說是無感知的,并且能帶來比較明顯的資源加載速度的提升,因此對目前所有一線互聯網產品來說,使用 CDN 已經不是一條建議,而是一個規定。

      針對靜態資源

      • CDN 網絡能夠緩存網站資源來提升首次請求的響應速度,但并非能適用于網站所有資源類型,它往往僅被用來存放網站的靜態資源文件。所謂靜態資源,就是指不需要網站業務服務器參與計算即可得到的資源,包括第三方庫的 JavaScript 腳本文件、樣式表文件及圖片等,這些文件的特點是訪問頻率高、承載流量大,但更新修改頻次低,且不與業務有太多耦合。

      • 如果是動態資源文件,比如依賴服務器端渲染得到的 HTML 頁面,它需要借助服務器端的數據進行計算才能得到,所以它就不適合放在 CDN 緩存服務器上。

      核心功能

      • CDN 網絡的核心功能包括兩點:緩存與回源,緩存指的是將所需的靜態資源文件復制一份到 CDN 緩存服務器上;回源指的是如果未在 CDN 緩存服務器上查找到目標資源,或 CDN 緩存服務器上的緩存資源已經過期,則重新追溯到網站根服務器獲取相關資源的過程。

      • 由于這兩個過程與前端性能優化的關系并非特別緊密,所以此處僅介紹概念,暫不進行深入分析。

      應用場景

      • 以淘寶為例 如下圖

        此時打開 Chrome 開發者工具的 Network 選項卡,來查看網站為渲染出該效果此時打開 Chrome 開發者工具的 Network 選項卡,來查看網站為渲染出該效果都請求了哪些資源,我們很容易發現除了從業務服務器返回的一個未完全加載資源的 HTML 文件,還包括了許多圖片、JavaScript 文件及樣式表文件,具體內容如圖所示。

        接著我們進一步去查看靜態資源所請求的URL,并列舉幾種不同類型的資源文件如下:

        從上述資源文件的請求域名中我們可以發現,這些文件都是從 CDN 網絡上獲取的,JavaScript 和樣式表這樣的文本文件與圖片文件使用的是不同的 CDN 域名,而且 CDN 域名與主站域名也完全不同,這樣的設計也是出于對性能的考慮,下面來分析具體的優化原理。

        優化實踐

      • 關于 CDN 的性能優化,如何能將其效果發揮到最大程度?其中包括了許多可實踐的方面,比如 CDN 服務器本身的性能優化、動態資源靜態邊緣化、域名合并優化和多級緩存的架構優化等,這些可能需要前端工程師與后端工程師一起配合,根據具體場景進行思考和解決,這里僅介紹一個與前端關系密切的 CDN 優化點:域名設置。
        我們以上面示例來說明,主站請求的域名是www。taobao.com ,而靜態資源請求的 CDN 服務器的域名有 g.alicdn.com 和 img.alicdn.com 兩種,他買是有一設計與主站域名不同的,這樣原因主要有兩點:第一點是避免對靜態資源的請求攜帶不必要的 Cookie 信息,第二點是考慮瀏覽器對統一域名下并發請求的限制。

  • 首先對第一點來說,Cookie 的訪問遵循同源策略,并且同一域名下的所有請求都會攜帶全部 Cookie 信息。
    雖然 Cookie 的存儲空間就算存滿也并不是很大,但如果將所有資源請求都放在主站域名下,那么所產生的效果對于任何一個圖片、JavaScript 腳本及樣式表等靜態資源文件的請求,都會攜帶完整的 Cookie 信息,若這些完全沒有必要的開銷積少成多,那么它們所產生的流量浪費就會很大,所以將 CDN 服務器的域名和主站域名進行區分是非常有價值的實踐。
  • 其次是第二點,因為瀏覽器對于同域名下的并發請求存在限制,通常 Chrome 的并發限制數是 6,其他瀏覽器可能多少會有所差異。這種限制也同時為我們提供了一種解決方案:通過增加類似域名的方式來提高并發請求數,比如對多個圖片文件進行并發請求的場景,可以通過擴展如下類似域名的方式來規避限制:

    雖然這種方式對于多并發限制是有效的,但是緩存命中是要根據整個 URL 進行匹配的,如果并發請求了相同的資源卻又使用了不同的域名,那么圖片之前的緩存就無法重用,也降低了緩存的命中,對于這種情況我們應該考慮進行恰當的域名合并優化。
  • 總結

    以上是生活随笔為你收集整理的http缓存小记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。