淺談Web緩存-緩存的實現過程詳解
在前端開發中,性能一直都是被大家所重視的一點,然而判斷一個網站的性能最直觀的就是看網頁打開的速度。其中提高網頁反應速度的一個方式就是使用緩存。一個優秀的緩存策略可以縮短網頁請求資源的距離,減少延遲,並且由於緩存文件可以重復利用,還可以減少帶寬,降低網絡負荷。那麽下面我們就來看看服務器端緩存的原理。
緩存分類
web緩存分為很多種,比如數據庫緩存、代理服務器緩存、還有我們熟悉的CDN緩存,以及瀏覽器緩存。對於太多文字的閱讀其實我是拒絕的,於是就畫了個圖來解釋下。
瀏覽器通過代理服務器向源服務器發起請求的原理如下圖,
瀏覽器先向代理服務器發起Web請求,再將請求轉發到源服務器。它屬於共享緩存,所以很多地方都可以使用其緩存資源,因此對於節省流量有很大作用。
瀏覽器緩存是將文件保存在客戶端,在同一個會話過程中會檢查緩存的副本是否足夠新,在後退網頁時,訪問過的資源可以從瀏覽器緩存中拿出使用。通過減少服務器處理請求的數量,用戶將獲得更快的體驗
下面我就來著重講下傳說中的瀏覽器緩存。
瀏覽器緩存
頁面的緩存狀態是由header決定的,header的參數有四種:
一、Cache-Control:
1、max-age(單位為s)指定設置緩存最大的有效時間,定義的是時間長短。當瀏覽器向服務器發送請求後,在max-age這段時間裏瀏覽器就不會再向服務器發送請求了。
我們來找個資源看下。比如shang.qq.com上的css資源,max-age=2592000,也就是說緩存有效期為2592000秒(也就是30天)。於是在30天內都會使用這個版本的資源,即使服務器上的資源發生了變化,瀏覽器也不會得到通知。max-age會覆蓋掉Expires,後面會有討論。
2、s-maxage(單位為s)同max-age,只用於共享緩存(比如CDN緩存)。
比如,當s-maxage=60時,在這60秒中,即使更新了CDN的內容,瀏覽器也不會進行請求。也就是說max-age用於普通緩存,而s-maxage用於代理緩存。如果存在s-maxage,則會覆蓋掉max-age和Expires header。
3、public 指定響應會被緩存,並且在多用戶間共享。也就是下圖的意思。如果沒有指定public還是private,則默認為public。
4、private 響應只作為私有的緩存(見下圖),不能在用戶間共享。如果要求HTTP認證,響應會自動設置為private。
5、no-cache 指定不緩存響應,表明資源不進行緩存,比如,
但是設置了no-cache之後並不代表瀏覽器不緩存,而是在緩存前要向服務器確認資源是否被更改。因此有的時候只設置no-cache防止緩存還是不夠保險,還可以加上private指令,將過期時間設為過去的時間。
6、no-store 絕對禁止緩存,一看就知道如果用了這個命令當然就是不會進行緩存啦~每次請求資源都要從服務器重新獲取。
7、must-revalidate指定如果頁面是過期的,則去服務器進行獲取。這個指令並不常用,就不做過多的討論了。
二、Expires
緩存過期時間,用來指定資源到期的時間,是服務器端的具體的時間點。也就是說,Expires=max-age + 請求時間,需要和Last-modified結合使用。但在上面我們提到過,cache-control的優先級更高。 Expires是Web服務器響應消息頭字段,在響應http請求時告訴瀏覽器在過期時間前瀏覽器可以直接從瀏覽器緩存取數據,而無需再次請求。
三、Last-modified
服務器端文件的最後修改時間,需要和cache-control共同使用,是檢查服務器端資源是否更新的一種方式。當瀏覽器再次進行請求時,會向服務器傳送If-Modified-Since報頭,詢問Last-Modified時間點之後資源是否被修改過。如果沒有修改,則返回碼為304,使用緩存;如果修改過,則再次去服務器請求資源,返回碼和首次請求相同為200,資源為服務器最新資源。
如下圖,最後修改時間為2014年12月19日星期五2點50分47秒
四、ETag
根據實體內容生成一段hash字符串,標識資源的狀態,由服務端產生。瀏覽器會將這串字符串傳回服務器,驗證資源是否已經修改,如果沒有修改,過程如下:
使用ETag可以解決Last-modified存在的一些問題:
a、某些服務器不能精確得到資源的最後修改時間,這樣就無法通過最後修改時間判斷資源是否更新
b、如果資源修改非常頻繁,在秒以下的時間內進行修改,而Last-modified只能精確到秒
c、一些資源的最後修改時間改變了,但是內容沒改變,使用ETag就認為資源還是沒有修改的。
使用緩存流程
還是用圖說話,下面是我所總結的從瀏覽器請求到展示資源的過程:
cache-control指令使用
說了那麽多cache-control的指令,那麽如何選擇使用哪些指令呢?我還是不說話==
額外的
除了開頭提到的那麽多緩存方式以外,還有一種我們都熟悉的緩存方式,LocalStorage和sessionStorage(好像是兩種23333)。
LocalStorage是一種本地存儲的公共資源,域名下很多應用共享這份資源會有風險;LocalStorage是以頁面域名劃分的,如果有多個等價域名之間的LocalStorage不互通,則會造成緩存多份浪費。
LocalStorage在PC上的兼容性不太好,而且當網絡速度快、協商緩存響應快時使用localStorage的速度比不上304。並且不能緩存css文件。而移動端由於網速慢,使用localStorage要快於304。
在html中加載一個png圖,首次加載的時候時間如下圖,
然而將圖片使用了LocalStorage存儲後,再次刷新後加載時間為0。
而相對LocalStorage來說,SessionStorage的數據只存儲到特定的會話中,不屬於持久化的存儲,所以關閉瀏覽器會清除數據。和localstorage具有相同的方法。
在前端開發中緩存是必不可少的,那麽使用怎樣的緩存方式更高效、讓我們項目的性能更優,還是需要我們仔細斟酌。
原創文章轉載請註明:
轉載自AlloyTeam:http://www.alloyteam.com/2016/03/discussion-on-web-caching/
淺談Web緩存-緩存的實現過程詳解