瀏覽器的緩存機制小結


什么是瀏覽器緩存?

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

  我們可以通過 chrome://view-http-cache/ 來查看chrome瀏覽器緩存了什么內容。 

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

 

為什么要用瀏覽器緩存?

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

  注意,一般,我們緩存的都是css、js、圖片之類的文件,這些文件的改動比較小,而html文件是不緩存的,因為html文件中常常包含動態的內容,比如引入a.css?v=1.0,最后是版本號,如果html也被緩存,那么我們就沒辦法達到通過修改版本號進而使得用戶獲取新內容的目的了。

 

 

瀏覽器緩存有哪些類型?

  緩存類型分為強緩存協商緩存

  強緩存:在用戶請求資源時,如果命中強緩存,則不向服務器請求,而直接從本地獲取資源。我們可以看到200狀態碼,並提示from disk cache或from memory cache(區別后面講)。 

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

  強緩存和協商緩存的共同點:兩者命中后都是從本地讀取資源。

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

 

瀏覽器緩存有關的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,百度都把它當做數據存儲來使用。這種緩存在互聯網行業當中,大量應用。
缺點:
需要人維護,消耗大量內存,需要設置過期時間

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM