瀏覽器的緩存機制小結

什麼是瀏覽器緩存?

  瀏覽器緩存(Brower Caching)是瀏覽器在本地磁盤對用戶最近請求過的文檔進行存儲,當訪問者再次訪問同一頁面時,瀏覽器就能夠直接從本地磁盤加載文檔php

  咱們能夠經過 chrome://view-http-cache/ 來查看chrome瀏覽器緩存了什麼內容。 css

  推薦閱讀文章:大公司裏怎樣開發和部署前端代碼?html

 

爲何要用瀏覽器緩存?

  • 第一:避免了冗餘的數據傳輸,節省流量。
  • 第二:加快了用戶訪問網頁的速度。
  • 第三:減少了服務器的壓力。

  注意,通常,咱們緩存的都是css、js、圖片之類的文件,這些文件的改動比較小,而html文件是不緩存的,由於html文件中經常包含動態的內容,好比引入a.css?v=1.0,最後是版本號,若是html也被緩存,那麼咱們就沒辦法達到經過修改版本號進而使得用戶獲取新內容的目的了。前端

 

 

瀏覽器緩存有哪些類型?

  緩存類型分爲強緩存協商緩存nginx

  強緩存:在用戶請求資源時,若是命中強緩存,則不向服務器請求,而直接從本地獲取資源。咱們能夠看到200狀態碼,並提示from disk cache或from memory cache(區別後面講)。 redis

  協商緩存: 在用戶請求資源時,瀏覽器直接則向服務器發送請求,服務器根據 request header 來判斷是否命中協商緩存,若是命中,則返回304和新的response header,使用本地資源;不然,返回新的資源。 chrome

  強緩存和協商緩存的共同點:二者命中後都是從本地讀取資源。數據庫

  強緩存和協商緩存的區別: 強緩存很強勢,是沒有向服務器發出請求的; 而協商緩存必需要向服務器發一個請求來協商。 apache

 

瀏覽器緩存有關的header

強緩存

  強緩存是利用http的響應頭中的Expires字段和Cache-Control兩個字段來控制的,用來表示使用緩存的有效時間。瀏覽器

Expires

  Expires是http1.0規範的,表示緩存的過時時間。  如某個資源的response heade中的字段: Expires: Fri, 18 Aug 2017 07:57:17 GMT。 表示當瀏覽器再次加載這個資源時,若是時間沒有超過,就命中強緩存,使用內存中緩存的資源。

之因此瀏覽器在再次加載時能夠判斷出時間是否超過,是由於瀏覽器在緩存資源時,不只緩存了資源,還緩存了response header相關的內容,好比這裏Expires字段。

缺點:因爲不能保證服務器和用戶端的絕對時間保持一致,因此緩存有時可能會出現混亂的狀況, 在HTTP1.1版本中開始使用Cache-Control的方法進行緩存。

 

 

Cache-Control

  Cache-Control是http1.1規範的,一樣表示緩存的過時時間。 其中的max-age是做爲判斷是否過時的主要判據,它是一個相對時間,單位爲s。 如知乎上的某一張圖片的response header中的字段:cache-control: public, max-age=31536000。 public表明了這張圖片是能夠被任何用戶緩存的,包括代理服務器等; 而max-age是表示在31536000s(一年)內,若是再次請求就使用本地資源。

  Cache-Control除了max-age的使用以外,還有幾個比較重要的字段:

  • no-cache: 不優先使用本地緩存,而是使用協商緩存。注意: 這裏並非說必定不適用本地緩存的資源,而是須要先協商一下,若是命中,仍是會使用本地緩存的。
  • no-store:必定不使用本地緩存,每次用戶請求資源,都會下載獲得服務器發來的最新的資源。
  • public:資源能夠被任何用戶緩存,包括全部普通用戶和代理服務器。
  • private:只能被當前的特定用戶緩存,其餘用戶沒法緩存。 通常是說代理服務器不能緩存。 

  

強緩存之Expires、Cache-Control比較

相同點: 二者都是強緩存。

不一樣點

  • Expires是http1.0規定的,而Cache-Control是http1.1規定的。
  • Expires的過時時間採用的是絕對時間,容易形成差錯; 而Cache-Control的過時時間採用的時相對時間,在緩存上不會出現問題。
  • 二者能夠同時存在於一次請求中,可是不會同時在一次請求中起做用。 在HTTP1.0的環境下,Cache-Control不起做用,Expires起做用; 在HTTP1.1的環境之下, Expires不起做用,而Cache-Control起做用。當前通常都是http1.1的狀況,因此Expires是做爲一種向下兼容的形式而存在的。
  • Cache-Control的選擇更多,功能更爲強大,推薦使用。 Expires做爲強緩存,功能單一,不推薦使用。

 

協商緩存

  協商緩存通常是使用 if-modified-since/last-modified 和 if-none-match/etag 由服務器來決定瀏覽器緩存的資源是否可使用

 

if-modified-since/last-modified

        在用戶請求到資源以後,會返回這個資源,而且在response header中返回一個 last-modifed 字段,這時瀏覽器就會緩存這個資源以及最後的修改時間, 能夠是: last-modified: Fri, 18 Aug 2017 07:27:24 GMT。 接着,當用戶再次請求相同的資源時,須要在請求頭中添加 if-modified-since 字段,這個字段的值就是以前存儲的 last-modifed 的值,服務器獲得 if-modified 值以後,會和資源最近的修改時間做比較,若是命中,則返回304,讓瀏覽器使用緩存的資源;不然,返回一個最新的資源而且在 last-modified 修改成最近的資源修改時間。 

 

if-none-match/etag

  在用戶請求到資源以後,會返回這個資源,而且在response heade 中返回一個 etag 字段,即 entity tag,這個字段的值是一個字符串,惟一的標識了這個資源,只要資源發生了變化,這個etag值就會發生變化。當用戶再次請求資源時,會在request header中攜帶 if-none-match 字段,其值爲上次緩存的 etag 值,若是命中,則返回304,使用緩存資源;不然,服務器返回最新的資源。

 

兩種協商緩存機制的比較

相同點: 都是爲了協商緩存。 

不一樣點

  • 在精度上,Etag優於last-modified。 若是一個文件在1s內改變了不少次,經過etag是能夠判斷出來並返回最新的資源的,可是last-modifed的精度只能到s,是沒法返回最新資源的,準確地說,UNIX記錄只能精確到s。 
  • 在準確率上,Etag優於last-modified。有些文件可能總體copy等,只是在時間上發生了變化,而內容上並無發生變化(etag變化,last-modified不變),若是使用last-modified,那麼就會返回最新的資源,實際上這是不須要的。
  • 在性能上,last-modified優於Etag。由於last-modified只須要記錄時間,而etag須要從新由服務器生成一個hash值,因此在性能上etag略差。
  • 在優先級上,Etag優於last-modified。  也就是說,etag和last-modified是能夠同時使用的,可是到服務器端,會優先判斷etag,若是相同,直接返回304;若是不一樣,就繼續比較last-modified,而後再決定是否返回新的資源。

 

 

瀏覽器緩存過程是怎樣的?

  1.  瀏覽器第一次加載資源,服務器返回200, 瀏覽器將資源下載下來,把資源和response header相關內容一併緩存。
  2. 下一次加載時,首先比較cache-control,若是沒有超過期間,則命中強緩存,不發送請求,直接讀取本地文件(若是不支持http1.1,則使用expires來判斷);若是時間已通過期,則發送帶有if-none-match和if-modified-since的請求頭。
  3. 服務器接受到請求以後,首先判斷etag是否和服務器上文件的etag一致,若是一致,則命中協商緩存,返回304;若是不一致,返回新的資源並帶上新的etag值返回200。
  4. 若是請求中沒有etag值,則比較發送來的 if-modified-since 值,若是命中,則返回304,;不然,返回新的資源帶上新的last-modified的值並返回狀態碼200。

 

 

用戶行爲對瀏覽器緩存的控制如何? 

  1. 地址欄訪問,連接跳轉是正經常使用戶行爲,將會觸發瀏覽器緩存機制
  2. F5刷新,瀏覽器會設置max-age=0,跳過強緩存判斷,進行協商緩存判斷
  3. ctrl+F5刷新,跳過強緩存和協商緩存,直接從服務器拉取資源

 

 

實際問題分析

  代碼更新到線上後用戶瀏覽器不能自行更新,咱們不能要求客戶在系統更新後都進行一次緩存清理的操做。
在資源請求的URL中增長一個參數,好比:js/mian.js?ver=0.7.1。這個參數是一個版本號,每一次部署的時候變動一下,當這個參數變化的時候,強緩存都會失效並從新加載。這樣一來,靜態資源,部署之後就須要從新加載。這樣就比較完美的解決了問題。

 

網站的緩存類型? 

第一級、瀏覽器緩存

優勢: 

這是最省資源的方式,瀏覽器甚至都不須要發起請求。 

 

缺點:

緩存脫離控制,若是緩存時間太長,用戶沒法訪問最新的頁面,特別是出現一個緊急的bug的時候,須要一段時間,才能平息。

 

使用:

在header頭部添加Expires、Cache-Control、max-age、last-modified、etag的一個或者是多個,能夠在meta中對緩存進行控制。 

 

建議:

js、css、圖片能夠把緩存時間設置的久一些,永遠不過時都是能夠的,文件出現變化的時候經過更換(添加)版本號就行更新

 

 

第二級、CDN緩存-靜態頁面

根據智能DNS解析,用戶訪問到最近的一臺機器,這樣就能夠減小網絡延遲。

用戶訪問CDN,CDN上若是資源存在而且沒有過時,直接返回給用戶內容,不然須要先訪問源站,而後保存到CDN服務器上面,而後返回用戶。

優勢

(1)請求分散,削弱了高流量下的壓力。

(2)減小了網絡延遲。

 

缺點

(1)節點資源可能緩存不一致,致使不一樣的用戶看到的結果不一樣

(2)若是設置過時時間短或者其餘的不合理的回源策略(即又訪問源服務器),會致使大量回源,致使訪問速度變慢。

(3)高併發期間,一個資源,可能會有多個回源請求。

(4)刷新CDN,須要一段時間, 若是出現bug, 也得登上幾分鐘。

 

 

第三級、proxy緩存-動態頁面

  不少代理服務器都支持了緩存,好比Nginx,Apache。一些動態頁面或者接口不怎麼更新,好比產品列表等,能夠把內容緩存到服務器裏面,下次請求的時候,直接讀取緩存,動態腳本都不須要執行。動態腳本若是要返回的話,可能須要訪問數據庫,以及一些其餘的服務,這就增長了相應時間。

使用:

nginx,能夠配置 proxy_cache

apache,能夠配置 mod_cache、mod_disk_cache、mod_file_cache以及mod_mem_cache

 

 

第四級、opcode緩存

  是針對php代碼。php執行的時候,須要先對php代碼解釋,生成中間代碼,稱爲opcode,而後再執行。若是緩存住,就能夠不須要每一次都解釋,這樣就能夠節省很多資源,增長吞吐量。

優勢:

節省資源,增長吞吐量。

 

缺點:

(1)代碼更新,須要等待opcode失效,若是設置不過時,那就須要重啓服務器。 

(2)opcode主要節省了CPU和內存資源,若是時間消耗主要是磁盤或者是網絡IO,那麼做用不是太大。

 

 

第五級、文件緩存

  會把計算或者從數據庫,以及其餘服務得到數據,放到一個文件裏面,使用的時候取出來。常見的session就是這麼作的。我看phpcms就大量使用這種緩存。
缺點:
1)多臺服務器,數據緩存內容可能不一致。爲了解決這個問題,曾經掛載共享代理,這就致使磁盤IO成爲瓶頸。
2)設置過時時間,不太容易。

 

 

第六級、分佈式緩存

爲了解決文件緩存存在的問題,就出現了分佈式緩存。常見的有memcache,redis.能夠搭建集羣,設置過時時間。redis,百度都把它當作數據存儲來使用。這種緩存在互聯網行業當中,大量應用。缺點:須要人維護,消耗大量內存,須要設置過時時間

相關文章
相關標籤/搜索