最近在對CDN進行優化,對瀏覽器緩存深刻研究了一下,記錄一下,方便後來者瀏覽器
畫了一個草圖:緩存
每一個狀態的詳細說明以下:服務器
1、Last-Modified負載均衡
在瀏覽器第一次請求某一個URL時,服務器端的返回狀態會是200,內容是你請求的資源,同時有一個Last-Modified的屬性標記(HttpReponse Header)此文件在服務期端最後被修改的時間,格式相似這樣:分佈式
Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT優化
客戶端第二次請求此URL時,根據HTTP協議的規定,瀏覽器會向服務器傳送If-Modified-Since報頭(HttpRequest Header),詢問該時間以後文件是否有被修改過:spa
If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMTorm
若是服務器端的資源沒有變化,則自動返回HTTP304(NotChanged.)狀態碼,內容爲空,這樣就節省了傳輸數據量。當服務器端代碼發生改變或者重啓服務器時,則從新發出資源,返回和第一次請求時相似。從而保證不向客戶端重複發出資源,也保證當服務器有變化時,客戶端可以獲得最新的資源。資源
注:若是If-Modified-Since的時間比服務器當前時間(當前的請求時間request_time)還晚,會認爲是個非法請求it
2、Etag工做原理
HTTP協議規格說明定義ETag爲「被請求變量的實體標記」(參見14.19)。簡單點即服務器響應時給請求URL標記,並在HTTP響應頭中將其傳送到客戶端,相似服務器端返回的格式:
Etag:「5d8c72a5edda8d6a:3239″
客戶端的查詢更新格式是這樣的:
If-None-Match:「5d8c72a5edda8d6a:3239″
若是ETag沒改變,則返回狀態304。
即:在客戶端發出請求後,HttpReponse Header中包含Etag:「5d8c72a5edda8d6a:3239″
標識,等於告訴Client端,你拿到的這個的資源有表示ID:5d8c72a5edda8d6a:3239。當下次須要發Request索要同一個URI的時候,瀏覽器同時發出一個If-None-Match報頭(Http RequestHeader)此時包頭中信息包含上次訪問獲得的Etag:「5d8c72a5edda8d6a:3239″標識。
If-None-Match:「5d8c72a5edda8d6a:3239「
,這樣,Client端等於Cache了兩份,服務器端就會比對2者的etag。若是If-None-Match爲False,不返回200,返回304(Not Modified) Response。
3、Expires
給出的日期/時間後,被響應認爲是過期。如Expires:Thu, 02 Apr 2009 05:14:08 GMT
需和Last-Modified結合使用。用於控制請求文件的有效時間,當請求數據在有效期內時客戶端瀏覽器從緩存請求數據而不是服務器端.當緩存中數據失效或過時,才決定從服務器更新數據。
4、Last-Modified和Expires
Last-Modified標識可以節省一點帶寬,可是仍是逃不掉髮一個HTTP請求出去,並且要和Expires一塊兒用。而Expires標識卻使得瀏覽器乾脆連HTTP請求都不用發,好比當用戶F5或者點擊Refresh按鈕的時候就算對於有Expires的URI,同樣也會發一個HTTP請求出去,因此,Last-Modified仍是要用的,並且要和Expires一塊兒用。
5、Etag和Expires
若是服務器端同時設置了Etag和Expires時,Etag原理一樣,即與Last-Modified/Etag對應的HttpRequestHeader:If-Modified-Since和If-None-Match。咱們能夠看到這兩個Header的值和WebServer發出的Last-Modified,Etag值徹底同樣;在徹底匹配If-Modified-Since和If-None-Match即檢查完修改時間和Etag以後,服務器才能返回304.
6、Last-Modified和Etag
分佈式系統裏多臺機器間文件的last-modified必須保持一致,以避免負載均衡到不一樣機器致使比對失敗
分佈式系統儘可能關閉掉Etag(每臺機器生成的etag都會不同)
Last-Modified和ETags請求的http報頭一塊兒使用,服務器首先產生Last-Modified/Etag標記,服務器可在稍後使用它來判斷頁面是否已經被修改,來決定文件是否繼續緩存
過程以下:
1.客戶端請求一個頁面(A)。
2.服務器返回頁面A,並在給A加上一個Last-Modified/ETag。
3.客戶端展示該頁面,並將頁面連同Last-Modified/ETag一塊兒緩存。
4.客戶再次請求頁面A,並將上次請求時服務器返回的Last-Modified/ETag一塊兒傳遞給服務器。
5.服務器檢查該Last-Modified或ETag,並判斷出該頁面自上次客戶端請求以後還未被修改,直接返回響應304和一個空的響應體。
注:
1、Last-Modified和Etag頭都是由WebServer發出的HttpReponse Header,WebServer應該同時支持這兩種頭。
2、WebServer發送完Last-Modified/Etag頭給客戶端後,客戶端會緩存這些頭;
3、客戶端再次發起相同頁面的請求時,將分別發送與Last-Modified/Etag對應的HttpRequestHeader:If-Modified-Since和If-None-Match。咱們能夠看到這兩個Header的值和WebServer發出的Last-Modified,Etag值徹底同樣;
4、經過上述值到服務器端檢查,判斷文件是否繼續緩存;
七、關於 Cache-Control: max-age=秒 和 Expires
Expires = 時間,HTTP 1.0 版本,緩存的載止時間,容許客戶端在這個時間以前不去檢查(發請求)
max-age = 秒,HTTP 1.1版本,資源在本地緩存多少秒。
若是max-age和Expires同時存在,則被Cache-Control的max-age覆蓋。
Expires 的一個缺點就是,返回的到期時間是服務器端的時間,這樣存在一個問題,若是客戶端的時間與服務器的時間相差很大,那麼偏差就很大,因此在HTTP 1.1版開始,使用Cache-Control: max-age=秒替代。
Expires =max-age + 「每次下載時的當前的request時間」