Web緩存 - HTTP協議緩存

来源:https://www.cnblogs.com/laixiangran/archive/2018/04/29/8971119.html
-Advertisement-
Play Games

為什麼要使用 Web 緩存 Web緩存一般分為瀏覽器緩存、代理伺服器緩存以及網關緩存,本文主要講的是 瀏覽器緩存 ,其它兩種緩存大家自行去瞭解下。 Web 緩存游走於伺服器和客戶端之間。這個伺服器可能是源伺服器(資源所駐留的伺服器),數量可能是1個或多個;這個客戶端也可能是1個或多個。Web 緩存就 ...


為什麼要使用 Web 緩存

Web緩存一般分為瀏覽器緩存、代理伺服器緩存以及網關緩存,本文主要講的是 瀏覽器緩存,其它兩種緩存大家自行去瞭解下。

Web 緩存游走於伺服器和客戶端之間。這個伺服器可能是源伺服器(資源所駐留的伺服器),數量可能是1個或多個;這個客戶端也可能是1個或多個。Web 緩存就在伺服器-客戶端之間搞監控,監控請求,並且把請求輸出的內容(例如html頁面、 圖片和文件)(統稱為副本)另存一份;然後,如果下一個請求是相同的 URL,則直接請求保存的副本,而不是再次麻煩源伺服器。

使用緩存的2個主要原因:

  • 降低延遲:緩存離客戶端更近,因此,從緩存請求內容比從源伺服器所用時間更少,呈現速度更快,網站就顯得更靈敏。
  • 降低網路傳輸:副本被重覆使用,大大降低了用戶的帶寬使用,其實也是一種變相的省錢(如果流量要付費的話),同時保證了帶寬請求在一個低水平上,更容易維護了。

試想現在的大型網站,隨便一個頁面都是一兩百個請求,每天 pv 都是億級別,如果沒有緩存,用戶體驗會急劇下降(表現在等待請求的時間上)、同時伺服器壓力和網路帶寬都面臨嚴重的考驗。

瀏覽器緩存控制機制

瀏覽器緩存控制機制有三種:HTML5離線存儲和本地緩存、HTML Meta 標簽、HTTP 協議緩存。

HTML5離線存儲和本地緩存

該種緩存機制是運用 HTMl5 新推出一些支持離線應用的 API 來進行數據的緩存,比如 appcache、sessionStorage、localStorage等等。

appcache 通過定義一個描述文件(manifest file)來列出要下載和緩存的資源,manifest file 示例如下:

CACHE MANIFEST
# Comment

file.js
file.css

然後在 html 中引用:

<html manifest="./xxx.manifest">

sessionStorage、localStorage 的基本用法如下:

// localStorage 用法相似
sessionStorage.set('name', 'laixiangran') // 存儲數據
sessionStorage.get('name') // 獲取數據 'laixiangran'

本文暫時就不詳細介紹,後面我會單獨介紹這塊的內容。

HTML Meta 標簽

使用 HTML Meta 標簽,Web 開發者可以在 HTML 頁面的 <head> 節點中加入 <meta> 標簽,代碼如下:

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

上述代碼的作用是告訴瀏覽器當前頁面不被緩存,每次訪問都需要去伺服器拉取。

使用上很簡單,但只有部分瀏覽器可以支持,而且所有緩存代理伺服器都不支持,因為代理不解析 HTML 內容本身。

HTTP 協議緩存

HTTP 協議緩存是我們本文講解的重點,它是通過 HTTP 頭信息來控制緩存的,HTTP 頭信息可以讓你對瀏覽器和代理伺服器如何處理你的副本進行更多的控制。他們在 HTML 代碼中是看不見的,一般由 Web 伺服器自動生成。但是,根據你使用的伺服器,你可以在某種程度上進行控制。

瀏覽器請求流程

瀏覽器第一次請求流程圖:

該流程比較簡單了,瀏覽器在第一次請求的時候不存在緩存,直接從瀏覽器請求,等請求返回結果之後再根據 HTTP 頭信息將數據緩存在記憶體或者硬碟中。

瀏覽器再次請求時:

該流程就複雜多了,瀏覽器需要根據 HTTP 頭信息來判斷是否直接從緩存讀取數據還是交由伺服器來判斷是否從緩存讀取數據。

幾種狀態碼的區別:

下麵我們就從該流程中出現的 HTTP 狀態碼 200(from cache)和 304 來講解 HTTP 協議緩存中的 HTTP 頭信息。

200(from cache)

這種 HTTP 狀態碼表示不訪問伺服器,直接從緩存(記憶體或者硬碟)讀取數據。

看兩張圖:

從上面兩張圖,我們會看到狀態碼有點不一樣,分別是 200(from memory cache) 以及 200(from diks cache),這兩個的區別一個是從記憶體讀取數據,一個是從硬碟讀取數據,然後它們的先後順序是先從記憶體讀取,再從硬碟讀取。這裡我們就統稱為 200(from cache)

出現 200(from cache) 這種情況,我們需要關註 ExpiresCache-control 這兩種HTTP 頭信息欄位。

Expires

Expires 的中文意思是“有效期”。顯然,就是告訴瀏覽器緩存的有效期。如果過期,緩存會檢查源伺服器以確定文件是否改變了。

Expires 頭唯一的有效值是 HTTP 時間,其他值無效,不會去緩存的。註意:時間是格林威治時間(GMT),而不是本地時間。如下所示:

Expires: Mon, 29 Oct 2018 03:53:10 GMT

那麼看我們上面的兩張圖中的 Expires,它都是到 2018-10-29 03:53:10 過期,而我們本次請求的時間 Date 是 2018-04-29 03:53:10,因此本次請求直接從緩存讀取數據,返回 200(from cache)。

儘管 Expires 頭很有用,但它有一定的局限性:

  • 因為牽扯到時間,Web 伺服器端的時間必須和緩存的同步,否則很可能實現不了預期的結果 —— 緩存把過期的數據當成最新的數據,把最新的數據當作過期的數據。
  • 你很容易忘記給某內容設置了一個特定時間,如果返回內容的時候沒有更新這個過期時間,則每個請求都是上訪到伺服器,反而增加了負載和響應時間。
  • 最後呢,Expires 是 HTTP 1.0 的東西,現在預設瀏覽器均預設使用 HTTP 1.1,所以它的作用基本忽略。
Cache-Control

Cache-Control 與 Expires 的作用一致,都是指明當前資源的有效期,控制瀏覽器是否直接從瀏覽器緩存讀取數據還是重新發請求到伺服器讀取數據。只不過 Cache-Control 的選擇更多,設置更細緻,如果同時設置的話,其優先順序高於 Expires。

Cache-Control 有用的響應頭包括:

  • max-age=[秒]: 表示在這個時間範圍內緩存是新鮮的無需更新。類似 Expires 時間,不過這個時間是相對的,而不是絕對的。也就是某次請求成功後多少秒內緩存是新鮮的。
  • s-maxage=[秒]: 類似 max-age, 除了僅應用於共用緩存(如代理)。
  • public: 標記認證的響應才能夠被緩存。一般而言,需要認證 HTTP 請求內容會自動私有化(不會被緩存)。
  • privateN: 允許緩存專門為某一個用戶存儲響應,比方說在瀏覽器中;共用緩存一般不會,例如在代理中。
  • no-cache: 每次在釋放緩存副本之前都強制發送請求給源伺服器進行驗證,這在確保認證有效性上很管用(和 public 結合使用)或者保證內容必須是即時的,不得無視緩存的所有優點,如國內的微博、twitter等的刷新顯示。
  • no-store: 強制緩存在任何情況下都不要保留任何副本。
  • must-revalidate: 告訴緩存,我給你準備了一些關於新鮮度的信息,在表現的時候要嚴格遵循。HTTP 允許緩存在某些特定情況下返回過期數據,指定了這個屬性,相對於告訴緩存,你必須嚴格遵循我的規則。
  • proxy-revalidate: 類似 must-revalidate,除了只能應用於代理緩存。

使用如下所示:

Cache-Control: max-age=15811200

那麼看我們上面的兩張圖中的 Cache-Control,它在當前請求成功後15811200秒內都是有效的,因此本次請求直接從緩存讀取數據,返回 200(from cache)。如果從當前請求成功開始,過了15811200秒之後就會重新從伺服器請求新數據。

304

當瀏覽器通過 Expires 或者 Cache-control 判斷出緩存已經過期,那麼就需要重新發送請求到伺服器,讓伺服器判斷當前緩存是否可以繼續使用。

當伺服器判斷該緩存已經失效,那麼就會返回新數據,HTTP 狀態碼為 200;

當瀏覽器判斷該緩存還未失效,那麼就會返回 HTTP 狀態碼為 304 (無需包體,節省流量),告知瀏覽器繼續使用緩存。

那麼通過哪些 HTTP 頭信息欄位來判斷是否返回 200 還是 304 呢?那麼我們就請出接下來的主角: Last-Modified/If-Modified-SinceEtag/If-None-Match。這兩個欄位都需要配合 Cache-Control 使用。

Last-Modified/If-Modified-Since
  • Last-Modified: 標示這個響應資源的最後修改時間。web 伺服器在響應請求時,告訴瀏覽器資源的最後修改時間。

  • If-Modified-Since: 當資源過期時(使用 Cache-Control 標識的 max-age),發現資源具有 Last-Modified 聲明,則再次向 web 伺服器請求時帶上 If-Modified-Since,表示請求時間。web伺服器收到請求後發現有 If-Modified-Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源有被改動過,則響應資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應 HTTP 304 (無需包體,節省流量),告知瀏覽器繼續使用緩存。

Etag/If-None-Match

這是在 HTTP 1.1 中引入了一個新的驗證器。

  • Etag: web 伺服器響應請求時,告訴瀏覽器當前資源在伺服器的唯一標識(生成規則由伺服器決定)。Apache 中,ETag 的值,預設是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行 Hash 後得到的。

  • If-None-Match: 當資源過期時(使用 Cache-Control 標識的 max-age),發現資源具有 Etage 聲明,則再次向 web 伺服器請求時帶上 If-None-Match (Etag 的值)。web 伺服器收到請求後發現有 If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回 200 或 304。

Etag 優先於 Last-Modified

你可能會覺得使用 Last-Modified 已經足以讓瀏覽器知道本地的緩存副本是否足夠新,為什麼還需要 Etag(實體標識)呢?HTTP1.1 中 Etag 的出現主要是為瞭解決幾個 Last-Modified 比較難解決的問題:

  • Last-Modified 標註的最後修改只能精確到秒級,如果某些文件在1秒鐘以內,被修改多次的話,它將不能準確標註文件的修改時間。

  • 如果某些文件會被定期生成,當有時內容並沒有任何變化,但Last-Modified卻改變了,導致文件沒法使用緩存。

  • 有可能存在伺服器沒有準確獲取文件修改時間,或者與代理伺服器時間不一致等情形。

Etag 是伺服器自動生成或者由開發者生成的對應資源在伺服器端的唯一標識符,能夠更加準確的控制緩存。Last-Modified 與 ETag 是可以一起使用的,伺服器會優先驗證 ETag,一致的情況下,才會繼續比對 Last-Modified,最後才決定是否返回 304。

創建支持緩存網站的小技巧

通過上面的介紹,我們知道 HTTP 協議緩存的機制,目的就是讓你可以更靈活更細緻的控制瀏覽器緩存,從而讓你的網站的緩存更加友好,用戶體驗更完美。

下麵這些技巧也可以讓你網站的緩存更加友好:

  • 保持URL穩定: 這是緩存的金科玉律,如果你為不同頁面,不同用戶或不同網站提供相同的內容,他們應該使用相同的URL。 這是簡單卻非常行之有效的方法。例如,你的 HTML 中的某個引用地址是"/index.html", 則要一直使用這個地址。
  • 不同地方的圖片和其他元素 使用同一庫
  • 對於不經常改變的圖片/頁面啟用緩存,通過將 Cache-Control: max-age 頭信息的值設大一點。
  • 對於定期更新的內容通過指定 max-age 或過期時間實現緩存。
  • 如果資源改變了(尤其下載文件),改變其名字。由於一般這種資源會有很長的過期時間,而伺服器上一直是正確的版本;因此,鏈接這個下載資源的頁面需要要比較短的過期時間。否則,會出現伺服器的資源是新的,但頁面被緩存了,其中的鏈接地址還是舊的,就會出現新舊版本衝突的可能。
  • 萬不得已不要變動文件: 否則你要設置一個新的 Last-Modified 值。另外,當你更新站點的時候,只要上傳改動的那些文件,而不要把整個站點都覆蓋過去。
  • Cookie能不用就不用: Cookie 難以被緩存,且大多情境下是沒有必要的。如果你非得使用 Cookie,建議用在動態頁面上。
  • 減少SSL的使用: 因為共用緩存不能存儲認證頁面,只在必要的時候使用,並且在 SSL 頁面上減少圖片的使用。

SSL:全稱 Secure Socket Layer – 安全套接層,為 Netscape 所研發,用以保障在 Internet 上數據傳輸之安全,利用數據加密 (Encryption) 技術,可確保數據在網路上的傳輸過程中不會被截取及竊聽。目前一般通用的規格為 40 bit 的安全標準,美國則已推出 128 bit 的更高安全標準,但限制出境。只要 3.0 版本以上的 I.E. 或 Netscape 瀏覽器即可支持 SSL。

  • 使用 REDbot 檢查你的網站: 可以幫助你應用本文所介紹的一些概念。

REDbot:REDbot = RED + robot,是個機器人,檢查 HTTP 資源,看他們如何會表現,指出常見的問題,並提出改進建議。雖然它屬於 HTTP 一致性測試儀,但卻可以找到不少 HTTP 相關問題。

用戶行為與緩存

用戶的一些行為會影響到瀏覽器的緩存,具體如下:

完整流程圖


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 由於需要使用到cilk plus和std=c++14,所以決定將編譯器升級。 基本教程如下: 1.下載GCC源碼: 2.解壓: 3.下載編譯所需依賴項: 4.建立編譯輸出目錄: 5.進入輸出目錄,執行以下命令,並生成makefile文件: 6.編譯: 接下來就是等待了,整個過程大約40分鐘左右。PS ...
  • 在 linux 編譯內核時 make menuconfig 報了下麵的錯誤。 *** Unable to find the ncurses libraries or the *** required header files. *** 'make menuconfig' requires the n ...
  • 在解壓的 linux2.6.15 文件夾下 make menuconfig 的時候出現下麵的錯誤: Makefile:452: target 'config' given more than once in the same ruleMakefile:452: *** mixed implicit ...
  • 今天分享的是89c51系列單片機的內部資源定時器/計數器,在所有的嵌入式系統中都包含這兩個內部功能。首先先瞭解幾個定時器/計數器相關的概念:•時鐘周期:時鐘周期 T 是時序中最小的時間單位,具體計算的方法就是1/時鐘源頻率,(一般單片機採用的是11.0592mHz)•機器周期:我們的單片機完成一個操... ...
  • mysql> insert into student values(162111,'周帥','男',21,'CS'); ERROR 1062 (23000): Duplicate entry '16211160127' for key 'PRIMARY'(duplecate為重覆的意思) prima... ...
  • 進入官網www.mysql.com ,選擇downloads; 選擇 Community 再選擇MySQL community server 選擇5.7的版本,這個看自己選擇,有問題看標題 選擇5.7.22版本,windows系統類型 選擇下載包,並點擊dawnload 無需註冊,點擊下載 下載後安... ...
  • 先來兩個問題 很多時候,在直覺上,我們都會認為JS代碼在執行時都是自上而下一行一行執行的,但是實際上,有一種情況會導致這個假設是錯誤的。 按照傳統眼光,console.log(a)輸出的應該是undefined,因為var a在a = 2之後。但是,輸出的是2。 再看第二段代碼: 有人會想到第一段代 ...
  • JavaScript一種直譯式腳本語言,是一種動態類型、弱類型、基於原型的語言,內置支持類型。 JS作用:表單驗證,減輕服務端的壓力;添加頁面動畫效果;動態更改頁面內容;Ajax網路請求。 下麵簡單介紹JS的基礎知識: >>> JS基礎知識 一、基本結構 <script type="text/jav ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...