之前也有碰到面的基本都是計算機網絡,直接涼涼(因爲基本都忘了,面的時候已經說了不會,還在問,當時已經很想懟他了),後面要說的都是官話,前端工程師也許對各種具有炫酷效果的頁面的實現技巧、賞心悅目的 UI 框架更感興趣,但因此常常忽視了 HTTP協議這部分基礎內容。實際上,如果想要在專業技術道路上走得更堅實,絕對不能繞開學習 HTTP 協議這一環節。對基礎及核心部分的深入學習是成爲一名專業技術人員的前提,以不變應萬變纔是立足之本(你需要懂,因爲面試官會問,誰叫你在求職)。
客戶端緩存主要是HTTP協議定義的緩存機制(如 Expires, Cache-Control字段), 也有非HTTP協議定義的緩存,使用HTTP-MATE標籤
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
本來想自己寫,發現有一篇寫的很好:原文:https://blog.csdn.net/u010725720/article/details/52622416
web緩存的種類
1 數據庫緩存
數據庫緩存是一種數據庫層面的緩存方案。當web應用的關係比較複雜,數據庫中的表很多的時候,如果頻繁進行數據庫查詢,很容易導致數據庫不堪重荷。爲了提供查詢的性能,將查詢後的數據放到內存中進行緩存,下次查詢時,直接從內存緩存直接返回,提供響應效率。
2 CDN緩存
CDN緩存一般是由網站管理員自己部署,爲了讓他們的網站更容易擴展並獲得更好的性能。通常情況下,瀏覽器先向CDN網關發起Web請求,網關服務器後面對應着一臺或多臺負載均衡源服務器,會根據它們的負載請求,動態將請求轉發到合適的源服務器上。從瀏覽器角度來看,整個CDN就是一個源服務器,從這個層面來說,瀏覽器和服務器之間的緩存機制,在這種架構下同樣適用。
3 代理服務器緩存
代理服務器是瀏覽器和源服務器之間的中間服務器,瀏覽器先向這個中間服務器發起Web請求,經過處理後(比如權限驗證,緩存匹配等),再將請求轉發到源服務器。代理服務器緩存的運作原理跟瀏覽器的運作原理差不多,只是規模更大。
4 瀏覽器緩存
每個瀏覽器都實現了 HTTP 緩存,我們通過瀏覽器使用HTTP協議與服務器交互的時候,瀏覽器就會根據一套與服務器約定的規則進行緩存工作。
也是我們本文需要講解的重點
5 應用層緩存
應用層緩存是指我們在代碼層面上做的緩存。通過代碼邏輯,把曾經請求過的數據或資源等,緩存起來,再次需要數據時通過邏輯上的處理選擇可用的緩存的數據。
關於瀏覽器緩存
瀏覽器緩存是瀏覽器在本地磁盤對用戶最近請求過的文檔進行存儲,當訪問者再次訪問同一頁面時,瀏覽器就可以直接從本地磁盤加載文檔。
瀏覽器緩存的優點有:
- 減少了冗餘的數據傳輸,節省了網費
- 減少了服務器的負擔,大大提升了網站的性能
- 加快了客戶端加載網頁的速度
瀏覽器緩存是提升web性能的一大利器,但是瀏覽器緩存如果使用不當,也會產生很多問題,並不是很容易的事。所以,結合最近遇到的案例,本文對瀏覽器緩存相關的知識進行總結歸納,希望對讀者有所幫助。
瀏覽器緩存主要有兩類:協商緩存和強緩存,也有稱之爲緩存協商和徹底緩存
1)瀏覽器在加載資源時,先根據這個資源的一些http header判斷它是否命中強緩存,強緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會發請求到服務器。比如某個css文件,如果瀏覽器在加載它所在的網頁時,這個css文件的緩存配置命中了強緩存,瀏覽器就直接從緩存中加載這個css,連請求都不會發送到網頁所在服務器;
2)當強緩存沒有命中的時候,瀏覽器一定會發送一個請求到服務器,通過服務器端依據資源的另外一些http header驗證這個資源是否命中協商緩存,如果協商緩存命中,服務器會將這個請求返回,但是不會返回這個資源的數據,而是告訴客戶端可以直接從緩存中加載這個資源,於是瀏覽器就又會從自己的緩存中去加載這個資源;
3)強緩存與協商緩存的共同點是:如果命中,都是從客戶端緩存中加載資源,而不是從服務器加載資源數據;區別是:強緩存不發請求到服務器,協商緩存會發請求到服務器。
4)當協商緩存也沒有命中的時候,瀏覽器直接從服務器加載資源數據。
強緩存
強緩存是利用http的返回頭中的Expires或者Cache-Control兩個字段來控制的,用來表示資源的緩存時間。
Expires
該字段是http1.0時的規範,它的值爲一個絕對時間的GMT格式的時間字符串,比如Expires:Sun, 08 Jan 2017 01:08:21 GMT。這個時間代表着這個資源的失效時間,在此時間之前,即命中緩存。這種方式有一個明顯的缺點,由於失效時間是一個絕對時間,所以當服務器與客戶端時間偏差較大時,就會導致緩存混亂。
Cache-Control
Cache-Control是http1.1時出現的header信息,主要是利用該字段的max-age值來進行判斷,它是一個相對時間,例如Cache-Control:max-age=3600,代表着資源的有效期是3600秒。
cache-control除了該字段外,還有下面幾個比較常用的設置值:
Public:指示響應可被任何緩存區緩存。
Private:指示對於單個用戶的整個或部分響應消息,不能被共享緩存處理。這允許服務器僅僅描述當用戶的部分響應消息,此響應消息對於其他用戶的請求無效。
no-cache:指示請求或響應消息不能緩存
no-store:用於防止重要的信息被無意的發佈。在請求消息中發送將使得請求和響應消息都不使用緩存。
max-age:指示客戶機可以接收生存期不大於指定時間(以秒爲單位)的響應。
min-fresh:指示客戶機可以接收響應時間小於當前時間加上指定時間的響應。
max-stale:指示客戶機可以接收超出超時期間的響應消息。如果指定max-stale消息的值,那麼客戶機可以接收超出超時期指定值之內的響應消息。
Cache-Control與Expires可以在服務端配置同時啓用,同時啓用的時候Cache-Control優先級高。
協商緩存
協商緩存就是由服務器來確定緩存資源是否可用,所以客戶端與服務器端要通過某種標識來進行通信,從而讓服務器判斷請求資源是否可以緩存訪問,這主要涉及到下面兩組header字段,這兩組搭檔都是成對出現的,即第一次請求的響應頭帶上某個字段(Last-Modified或者Etag),則後續請求則會帶上對應的請求字段(If-Modified-Since或者If-None-Match),若響應頭沒有Last-Modified或者Etag字段,則請求頭也不會有對應的字段。
Last-Modify/If-Modify-Since
瀏覽器第一次請求一個資源的時候,服務器返回的header中會加上Last-Modify,Last-modify是一個時間標識該資源的最後修改時間,例如Last-Modify: Mon, 10 Oct 2016 08:29:58 Asia/Shanghai。
當瀏覽器再次請求該資源時,request的請求頭中會包含If-Modify-Since,該值爲緩存之前返回的Last-Modify。服務器收到If-Modify-Since後,根據資源的最後修改時間判斷是否命中緩存。
如果命中緩存,則返回304,並且不會返回資源內容,並且不會返回Last-Modify。
ETag/If-None-Match
與Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一個校驗碼。ETag可以保證每一個資源是唯一的,資源變化都會導致ETag變化。服務器根據瀏覽器上送的If-None-Match值來判斷是否命中緩存。
與Last-Modified不一樣的是,當服務器返回304 Not Modified的響應時,由於ETag重新生成過,response header中還會把這個ETag返回,即使這個ETag跟之前的沒有變化。
響應過程如下:
爲什麼要有Etag
HTTP1.1中Etag的出現主要是爲了解決幾個Last-Modified比較難解決的問題:
- 一些文件也許會週期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認爲這個文件被修改了,而重新GET;
- 某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);
- 某些服務器不能精確的得到文件的最後修改時間。
Last-Modified與ETag是可以一起使用的,服務器會優先驗證ETag,一致的情況下,纔會繼續比對Last-Modified,最後才決定是否返回304。
強緩存與協商緩存的區別可以用下表來表示:
緩存類型 | 獲取資源形式 | 狀態碼 | 發送請求到服務器 |
---|---|---|---|
強緩存 | 從緩存取 | 200(from cache) | 否,直接從緩存取 |
協商緩存 | 從緩存取 | 304(Not Modified) | 否,通過服務器來告知緩存是否可用 |
用戶行爲對緩存的影響
用戶操作 | Expires/Cache-Control | Last-Modied/Etag |
---|---|---|
地址欄回車 | 有效 | 有效 |
頁面鏈接跳轉 | 有效 | 有效 |
新開窗口 | 有效 | 有效 |
前進回退 | 有效 | 有效 |
F5刷新 | 無效 | 有效 |
Ctrl+F5強制刷新 | 無效 | 無效 |
緩存總結流程圖
cache-control指令使用