【轉載】瀏覽器緩存詳解:expires cache-control last-modified
最近在對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),詢問該時間之後文件是否有被修改過:
If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT
如果服務器端的資源沒有變化,則自動返回HTTP304(NotChanged.)狀態碼,內容為空,這樣就節省了傳輸數據量。當服務器端代碼發生改變或者重啟服務器時,則重新發出資源,返回和第一次請求時類似。從而保證不向客戶端重復發出資源,也保證當服務器有變化時,客戶端能夠得到最新的資源。
註:如果If-Modified-Since的時間比服務器當前時間(當前的請求時間request_time)還晚,會認為是個非法請求
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、通過上述值到服務器端檢查,判斷文件是否繼續緩存;
7、關於 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時間”
所以一旦重新下載的頁面後,expires就重新計算一次,但last-modified不會變化
【轉載】瀏覽器緩存詳解:expires cache-control last-modified