對於瀏覽器緩存,相信不少開發者對它真的是又愛又恨。一方面極大地提高了用戶體驗,而另外一方面有時會由於讀取了緩存而展現了「錯誤」的東西,而在開發過程當中想方設法地想把緩存禁掉。那麼瀏覽器緩存到底是個什麼樣的神奇玩意呢?html
簡單來講,瀏覽器緩存就是把一個已經請求過的Web資源(如html頁面,圖片,js,數據等)拷貝一份副本儲存在瀏覽器中。緩存會根據進來的請求保存輸出內容的副本。當下一個請求來到的時候,若是是相同的URL,緩存會根據緩存機制決定是直接使用副本響應訪問請求,仍是向源服務器再次發送請求。比較常見的就是瀏覽器會緩存訪問過網站的網頁,當再次訪問這個URL地址的時候,若是網頁沒有更新,就不會再次下載網頁,而是直接使用本地緩存的網頁。只有當網站明確標識資源已經更新,瀏覽器纔會再次下載網頁。node
好比說,在頁面請求以後,web資源都被緩存了,在後面的重複請求中,許多資源都是直接從緩存中讀取的(from cache),而不是從新去向服務器請求。web
(1)減小網絡帶寬消耗瀏覽器
不管對於網站運營者或者用戶,帶寬都表明着金錢,過多的帶寬消耗,只會便宜了網絡運營商。當Web緩存副本被使用時,只會產生極小的網絡流量,能夠有效的下降運營成本。緩存
(2)下降服務器壓力安全
給網絡資源設定有效期以後,用戶能夠重複使用本地的緩存,減小對源服務器的請求,間接下降服務器的壓力。同時,搜索引擎的爬蟲機器人也能根據過時機制下降爬取的頻率,也能有效下降服務器的壓力。服務器
(3)減小網絡延遲,加快頁面打開速度網絡
帶寬對於我的網站運營者來講是十分重要,而對於大型的互聯網公司來講,可能有時由於錢多而真的不在意。那Web緩存還有做用嗎?答案是確定的,對於最終用戶,緩存的使用可以明顯加快頁面打開速度,達到更好的體驗。負載均衡
對於瀏覽器端的緩存來說,這些規則是在HTTP協議頭和HTML頁面的Meta標籤中定義的。他們分別從新鮮度和校驗值兩個維度來規定瀏覽器是否能夠直接使用緩存中的副本,仍是須要去源服務器獲取更新的版本。分佈式
新鮮度(過時機制):也就是緩存副本有效期。一個緩存副本必須知足如下條件,瀏覽器會認爲它是有效的,足夠新的:
1. 含有完整的過時時間控制頭信息(HTTP協議報頭),而且仍在有效期內;
2. 瀏覽器已經使用過這個緩存副本,而且在一個會話中已經檢查過新鮮度;
知足以上兩個狀況的一種,瀏覽器會直接從緩存中獲取副本並渲染。
校驗值(驗證機制):服務器返回資源的時候有時在控制頭信息帶上這個資源的實體標籤Etag(Entity Tag),它能夠用來做爲瀏覽器再次請求過程的校驗標識。如過發現校驗標識不匹配,說明資源已經被修改或過時,瀏覽器需求從新獲取資源內容。
(1)使用HTML Meta 標籤
Web開發者能夠在HTML頁面的<head>節點中加入<meta>標籤,代碼以下
<meta http-equiv="Pragma" content="no-cache"> <!- Pragma是http1.0版本中給客戶端設定緩存方式之一,具體做用會在後面詳細介紹 -->
上述代碼的做用是告訴瀏覽器當前頁面不被緩存,每次訪問都須要去服務器拉取。可是!這裏有個坑...
事實上這種禁用緩存的形式用處頗有限:
a. 僅有IE才能識別這段meta標籤含義,其它主流瀏覽器僅識別「Cache-Control: no-store」的meta標籤。
b. 在IE中識別到該meta標籤含義,並不必定會在請求字段加上Pragma,但的確會讓當前頁面每次都發新請求(僅限頁面,頁面上的資源則不受影響)。
(2)使用緩存有關的HTTP消息報頭
在這裏就須要先跟你們介紹一下HTTP的相關知識。一個URI的完整HTTP協議交互過程是由HTTP請求和HTTP響應組成的。有關HTTP詳細內容可參考《Hypertext Transfer Protocol — HTTP/1.1》、《HTTP協議詳解》等。
在HTTP請求和響應的消息報頭中,常見的與緩存有關的消息報頭有:
在咱們對HTTP請求頭和響應頭的部分字段有了必定的認識以後,咱們接下來就來討論不一樣字段之間的關係和區別:
· Cache-Control與Expires
Cache-Control與Expires的做用一致,都是指明當前資源的有效期,控制瀏覽器是否直接從瀏覽器緩存取數據仍是從新發請求到服務器取數據。只不過Cache-Control的選擇更多,設置更細緻,若是同時設置的話,其優先級高於Expires。
· Last-Modified/ETag與Cache-Control/Expires
配置Last-Modified/ETag的狀況下,瀏覽器再次訪問統一URI的資源,仍是會發送請求到服務器詢問文件是否已經修改,若是沒有,服務器會只發送一個304回給瀏覽器,告訴瀏覽器直接從本身本地的緩存取數據;若是修改過那就整個數據從新發給瀏覽器;
Cache-Control/Expires則不一樣,若是檢測到本地的緩存仍是有效的時間範圍內,瀏覽器直接使用本地副本,不會發送任何請求。二者一塊兒使用時,Cache-Control/Expires的優先級要高於Last-Modified/ETag。即當本地副本根據Cache-Control/Expires發現還在有效期內時,則不會再次發送請求去服務器詢問修改時間(Last-Modified)或實體標識(Etag)了。
通常狀況下,使用Cache-Control/Expires會配合Last-Modified/ETag一塊兒使用,由於即便服務器設置緩存時間, 當用戶點擊「刷新」按鈕時,瀏覽器會忽略緩存繼續向服務器發送請求,這時Last-Modified/ETag將可以很好利用304,從而減小響應開銷。
· Last-Modified與ETag
你可能會以爲使用Last-Modified已經足以讓瀏覽器知道本地的緩存副本是否足夠新,爲何還須要Etag(實體標識)呢?HTTP1.1中Etag的出現主要是爲了解決幾個Last-Modified比較難解決的問題:
Etag是服務器自動生成或者由開發者生成的對應資源在服務器端的惟一標識符,可以更加準確的控制緩存。Last-Modified與ETag是能夠一塊兒使用的,服務器會優先驗證ETag,一致的狀況下,纔會繼續比對Last-Modified,最後才決定是否返回304。Etag的服務器生成規則和強弱Etag的相關內容能夠參考,《互動百科-Etag》和《HTTP Header definition》,這裏再也不深刻。
注意:
1. Etag是服務器自動生成或者由開發者生成的對應資源在服務器端的惟一標識符,可以更加準確的控制緩存,可是須要注意的是分佈式系統裏多臺機器間文件的last-modified必須保持一致,以避免負載均衡到不一樣機器致使比對失敗,Yahoo建議分佈式系統儘可能關閉掉Etag(每臺機器生成的etag都會不同,由於除了 last-modified、inode 也很難保持一致)。
2. Last-Modified/If-Modified-Since要配合Cache-Control使用,Etag/If-None-Match也要配合Cache-Control使用。
第一次請求:
再次請求:
瀏覽器緩存行爲還有用戶的行爲有關,具體狀況以下:
若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加Java進階羣895244712
,有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。
固然並非全部請求都能被緩存,沒法被瀏覽器緩存的請求以下:
1. HTTP信息頭中包含Cache-Control:no-cache,pragma:no-cache(HTTP1.0),或Cache-Control:max-age=0等告訴瀏覽器不用緩存的請求
2. 須要根據Cookie,認證信息等決定輸入內容的動態請求是不能被緩存的
3. 通過HTTPS安全加密的請求(有人也通過測試發現,ie其實在頭部加入Cache-Control:max-age信息,firefox在頭部加入Cache-Control:Public以後,可以對HTTPS的資源進行緩存,參考《HTTPS的七個誤解》)
4. POST請求沒法被緩存
5. HTTP響應頭中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的請求沒法被緩存
參考資料:
http://www.cnblogs.com/520yang/articles/4807408.html 瀏覽器 HTTP 協議緩存機制詳解
https://my.oschina.net/leejun2005/blog/369148 瀏覽器 HTTP 協議緩存機制詳解
http://web.jobbole.com/82997/ 瀏覽器緩存機制淺析
http://www.alloyteam.com/2012/03/web-cache-2-browser-cache/ Web瀏覽器的緩存機制
http://www.cnblogs.com/vajoy/p/5341664.html 淺談瀏覽器http的緩存機制