帶你10分鐘瞭解http的cache設置

cache

http的cache是以URL爲key的,因此不想用之前的緩存,則能夠更換URL,例如加不一樣的query、改文件名(如加上MD5或版本號)等。URL是忽略錨點的。git

瀏覽器檢驗vs服務器檢驗

Expires、 Cache-Control、Last-Modified、ETag是RFC2616(HTTP/1.1)協議中和網頁緩存相關的幾個字段。 前兩個用來控制緩存的失效日期,瀏覽器可經過它來斷定,需不須要發出HTTP請求; 後兩個用來驗證網頁的有效性,服務器端利用它來驗證這個文件是否須要從新返回。github

Last-Modified VS Etag

若是服務器端同時設置了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.算法

既然有了Last-Modified,爲何還要用ETag字段呢?由於若是在一秒鐘以內對一個文件進行兩次更改,Last-Modified就會不正確。所以,HTTP/1.1利用Entity Tag頭提供了更加嚴格的驗證。瀏覽器

注意:分佈式系統裏多臺機器間文件的last-modified必須保持一致,以避免負載均衡到不一樣機器致使比對失敗緩存

分佈式系統儘可能關閉掉Etag(每臺機器生成的etag都會不同)服務器

Last-Modified vs Expires

Last-Modified標識可以節省一點帶寬,可是仍是逃不掉髮一個HTTP請求出去,並且要和Expires一塊兒用。而Expires標識卻使得瀏覽器乾脆連HTTP請求都不用發,好比當用戶F5或者點擊Refresh按鈕的時候就算對於有Expires的URI,同樣也會發一個HTTP請求出去,因此,Last-Modified仍是要用的,並且要和Expires一塊兒用。網絡

304 vs 200(from cache)

  • 304由last-modified/etag控制,內容爲空負載均衡

  • 200(from cache)由expires/cache-control控制,瀏覽器本身的內存分佈式

    • expires,http1.0有效,是絕對時間,客戶端時間
    • cache-control,1.1有效,相對時間,會覆蓋expires,只要有效,瀏覽器訪問本身的緩存

Cache-Control: max-age=秒 vs Expires

Expires = 時間,HTTP 1.0 版本,緩存的載止時間,容許客戶端在這個時間以前不去檢查(發請求) max-age = 秒,HTTP 1.1版本,資源在本地緩存多少秒。 若是max-age和Expires同時存在,則被Cache-Control的max-age覆蓋。ui

Expires 的一個缺點就是,返回的到期時間是服務器端的時間,這樣存在一個問題,若是客戶端的時間與服務器的時間相差很大,那麼偏差就很大,因此在HTTP 1.1版開始,使用Cache-Control: max-age=秒替代。

Expires =max-age +   「每次下載時的當前的request時間」

因此一旦從新下載的頁面後,expires就從新計算一次,但last-modified不會變化

應用 HTTP/1.1 版本的緩存服務器遇到同時存在 Expires 首部字段的情 況時,會優先處理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的緩存服務器的狀況卻相反,max-age 指令會被忽略

cache-control

  • no-cache

    並不表明徹底的禁用緩存,而是表明會每次去核對服務端的 Etag,若是相同,那麼就不會去服務端下載完整的資源,返回一個 304 Not Modified。(最長緩存 3 年)

  • no-store

    纔是真正的禁用緩存,它表示每次服務端都會去下載最新的資源。(固然,一般彷佛都用不上)。

  • max-age

    最大緩存時長,max-age不要大於2^31,以避免大於int32而變成負數。

    在Response中設置max-age的時間信息,能夠在客戶端生成緩存文件,在緩存不過時的狀況下,客戶端不會直接向服務器請求數據,在緩存過時的狀況下,客戶端會向服務器直接請求生成新的緩存。

    若是同時設置了Response和Request中的max-age 緩存時間,若是Request中的max-age時間小於Response中的max-age時間,客戶端會根據Request中max-age時間週期去直接進行網絡請求,若是碰到斷網或者網絡請求不通的狀況,即便緩存還在有效期內(Response中設置的max-age時間足夠大),在Request設置的max-age過時以後,APP也會直接去進行網絡請求。

    所以能夠考慮在客戶端的設計中一個和好的網絡緩存場景,用Response的max-age控制緩存的時間,用Request中max-age控制刷新的時間和機制

  • max-stale

    緩存時長過時之後,還能夠有效。好比如今max-age:60秒,那麼max-stale:60秒,如今的緩存時長就是120秒,

  • min-fresh

    客戶機能夠接收響應時間小於當前時間加上指定時間的響應。   

    設定可以容忍的最小新鮮度(緩存時長)。min-fresh標示了客戶端不肯意接受新鮮度很少於當前的age加上min-fresh設定的時間之和的響應。

  • no-transfrom

    使用 no-transform 指令規定不管是在請求仍是響應中,緩存都不能改 變實體主體的媒體類型。

  • only-if-cache

    使用 only-if-cached 指令表示客戶端僅在緩存服務器本地緩存目標資源的狀況下,纔會要求其返回。換言之,該指令要求緩存服務器不從新加載響應,也不會再次確認資源有效性。若發生請求緩存服務器的本地緩存無響應,則返回狀態碼 504 Gateway Timeout。

  • cache-extension

    經過 cache-extension 標記(token),能夠擴展 Cache-Control 首部字 段內的指令。

  • public 和 private 的差異

    主要在於若是是有用戶認證環節的頁面,設置爲private 就只有終端瀏覽器會緩存,中間 CDN 並不會緩存,而設置爲 public,則會在每個環節緩存。默認不須要設置 public,由於 max-age 已經代表能夠由各個環節緩存了(單位爲秒)。此刻若是命中緩存,則不會再去請求服務器覈對 Etag,而是直接返回 200(from disk)。

    因爲 public 會在每個環節緩存,若是對修改更新預覽又強需求的網頁,那麼最好不要使用這一緩存策略,不然還須要刷新 CDN 源

  • s-max-age

    和max-age相似,它們的不一樣點是 s- maxage 指令只適用於供多位用戶使用的公共緩存服務器

  • must-revalidate

    使用 must-revalidate 指令,代理會向源服務器再次驗證即將返回的響應緩存目前是否仍然有效。若代理沒法連通源服務器再次獲取有效資源的話,緩存必須給客戶端 一條 504(Gateway Timeout)狀態碼。另外,使用 must-revalidate 指令會忽略請求的 max-stale 指令(即便已 經在首部使用了 max-stale,也不會再有效果)。

  • proxy-revalidate

    proxy-revalidate 指令要求全部的緩存服務器在接收到客戶端帶有該指 令的請求返回響應以前,必須再次驗證緩存的有效性。

Expires

表明何時過時,時間與客戶端時間比較
複製代碼

Last-Modified

上次修改時間,注:若是If-Modified-Since的時間比服務器當前時間(當前的請求時間request_time)還晚,會認爲是個非法請求。
複製代碼

Etag

被請求變量的實體標記,標識,等於告訴Client端,你拿到的這個的資源有表示ID:5d8c72a5edda8d6a:3239。當下次須要發Request索要同一個URI的時候,瀏覽器同時發出一個If-None-Match報頭(Http RequestHeader)此時包頭中信息包含上次訪問獲得的Etag:「5d8c72a5edda8d6a:3239″標識。

Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後獲得的

容量

容量是以總體計算的,不區分Domain。

Android WebView是20MB。iOS WebView也多是20MB(根據https://github.com/gnustep/base/blob/master/Source/NSURLCache.m,不肯定GNUstep是否也是Apple的源碼)。

PC上的Chromium是以80MB爲基準結合磁盤可用空間來考慮的,最大是320MB。算法是:

if (可用空間 < 100MB)
  容量 = 80%的可用空間  // < 80MB
else if (可用空間 < 800MB)
  容量 = 80MB
else if (可用空間 < 2000MB)  // 約2GB
  容量 = 10%的可用空間  // < 200MB
else if (可用空間 < 20000MB)  // 約20GB
  容量 = 200MB
else  // >= 20000MB
  容量 = Math.min(1%的可用空間, 320MB)  // 200MB <= 容量 <= 320MB

複製代碼

淘汰

淘汰算法是通常是LRU,

瀏覽器須要對緩存的文件進行索引,若是這個索引損壞,瀏覽器會刪除全部的緩存。用戶也能夠經過設置界面來刪除。此外,第三方程序也會作清理。

請求時緩存指令

  • no-cache

  • If-Modified-Since

    值是上次請求的last-modified值,詢問服務器

  • If-None-Match

    值是客戶端查詢的etag的值,詢問服務器是否變化

  • no-store

  • max-age

  • max-stale

  • min-fresh

  • only-if-cached

響應消息中的指令

  • public

  • private

  • no-cache

  • Last-Modified

    此文件在服務期端最後被修改的時間

  • Etag

    服務器響應時給請求URL標記,並在HTTP響應頭中將其傳送到客戶端。Etag:「5d8c72a5edda8d6a:3239″

  • no- store

  • no-transform

  • must-revalidate

  • proxy-revalidate

  • max-age

相關文章
相關標籤/搜索