先看上圖,若是對圖中的(a)(b)(c)(d)四個過程的處理方式都很清楚了,那麼請不用再看本文了。css
兩個概念
-
強緩存
用戶發送的請求,直接從客戶端緩存中獲取,不發送請求到服務器,不與服務器發生交互行爲。html -
協商緩存
用戶發送的請求,發送到服務器後,由服務器斷定是否從緩存中獲取資源。chrome -
二者共同點:客戶端得到的數據最後都是從客戶端緩存中得到。瀏覽器
-
二者的區別:從名字就能夠看出,強緩存不與服務器交互,而協商緩存則須要與服務器交互。緩存
四個過程詳解
(a)瀏覽器斷定是否有緩存
先理解個概念,所謂「客戶端緩存」就是指用戶設備中本地資源。不一樣瀏覽器緩存文件的地址也不盡相同。
咱們以chrome爲例來查看下瀏覽器緩存文件的地址,
1)首先在chrome中輸入:chrome://chrome-urls/,看到一堆列表,裏面隱藏了許多瀏覽器的奧祕,有興趣的能夠本身深扒。
2)找到 chrome://cache(固然也能夠直接輸入這個地址)
爲了驗證緩存,咱們打開百度,打開開發者模式,去掉disable-cache選項
服務器
從上圖中能夠看到,第一個從緩存中取的文件是: https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/css/super_min_fec0412a.css
而後回到chrome://cache 頁面,找到它,並點擊進去,能夠看到:
回到問題,瀏覽器怎麼斷定是否有緩存,就能夠轉化爲瀏覽器去讀取本地放緩存的地方(注:不一樣瀏覽器不一樣系統都會不一樣)是否有該對應的請求啦。markdown
總結來講就是個查找文件是否存在的問題。
(b)緩存是否過時
咱們再以這張圖爲例,這張圖中代表,客戶端保留了一個服務器端的response header。
裏面的Date字段代表這次緩存時服務器的時間。
裏面有兩個字段:expires 、Cache-Control負載均衡
-
expires
Http1.0 中的標準,代表過時時間,注意此處的時間都是指的是服務器的時間。
能夠看到過時時間被設定爲了:Thu, 28 Sep 2017 06:38:37 GMT分佈式存在的問題:服務器時間與客戶端時間的不一致,就會致使緩存跟期待效果出現誤差。
-
Cache-Control
Http1.1 中的標準,能夠當作是 expires 的補充。使用的是相對時間的概念。
簡單介紹下Cache-Control的屬性設置。
1)max-age: 設置緩存的最大的有效時間,單位爲秒(s)。max-age會覆蓋掉Expires
2) s-maxage: 只用於共享緩存,好比CDN緩存(s -> share)。與max-age 的區別是:max-age用於普通緩存,
而s-maxage用於代理緩存。若是存在s-maxage,則會覆蓋max-age 和 Expires.
3) public:響應會被緩存,而且在多用戶間共享。默認是public。
4) private: 響應只做爲私有的緩存,不能在用戶間共享。若是要求HTTP認證,響應會自動設置爲private。
5)no-cache: 指定不緩存響應,代表資源不進行緩存。可是設置了no-cache以後並不表明瀏覽器不緩存,而是在緩存前要向服務器確認資源是否被更改。所以有的時候只設置no-cache防止緩存仍是不夠保險,還能夠加上private指令,將過時時間設爲過去的時間。
6)no-store: 絕對禁止緩存。
7)must-revalidate: 若是頁面過時,則去服務器進行獲取。
設置cache-control 的規則能夠參見下圖:
post
因此判斷緩存是否過時步驟是:
1) 查看是否有cache-control 的max-age / s-maxage , 若是有,則用服務器時間date值 + max-age/s-maxage 的秒數計算出新的過時時間,將當前時間與過時時間進行比較,判斷是否過時
2)查看是否有cache-control 的max-age / s-maxage,則用expires 做爲過時時間比較
總結:(b)過程執行完後,若是斷定爲未過時,則使用客戶端緩存。那麼就是屬於「強緩存」。
(c)跟服務器協商是否使用緩存
到這一步的時候,瀏覽器會向服務器發送請求,同時若是上一次的緩存中有Last-modified 和 Etag 字段,
瀏覽器將在request header 中加入If-Modified-Since(對應於Last-modified), 和If-None-Match(對應於Etag)。
- Last-modified: 代表請求的資源上次的修改時間。
- If-Modified-Since:客戶端保留的資源上次的修改時間。
- Etag:資源的內容標識。(不惟一,一般爲文件的md5或者一段hash值,只要保證寫入和驗證時的方法一致便可)
-
If-None-Match: 客戶端保留的資源內容標識。
⚠️:
1) 分佈式系統儘可能關閉Etag,由於每臺機器生成的Etag都不同。
2)分佈式系統裏多臺機器間文件的Last-Modified必須一致,以避免負載均衡不一樣致使對比失敗。
一般狀況下,若是同時發送 If-None-Match 、If-Modified-Since字段,服務器只要比較etag 的內容便可,固然具體處理方式,看服務器的約定規則。
(d)協商緩存
在這個階段,服務器通常會將Cache-control、expires 、last-modified、date、etag 等字段在response header 中返回,便於下次緩存。固然具體的場景,也是看服務器的約定規則設定。
緩存的不一樣來源
⚠️: 這個問題暫時沒有找到很是滿意的、清楚的回答。
from disk cache
從磁盤中獲取緩存資源,等待下次訪問時不須要從新下載資源,而直接從磁盤中獲取。它的直接操做對象爲CurlCacheManager。
from memory cache
從內存中獲取資源,等待下次訪問時不須要從新下載資源,而直接從內存中獲取。Webkit早已支持memoryCache。
目前Webkit資源分紅兩類,一類是主資源,好比HTML頁面,或者下載項,一類是派生資源,好比HTML頁面中內嵌的圖片或者腳本連接,分別對應代碼中兩個類: MainResourceLoader和SubresourceLoader。雖然Webkit支持memoryCache,可是也只是針對派生資源,它對應的類爲CachedResource,用於保存原始數據(好比CSS,JS等),以及解碼過的圖片數據。
區別
當退出進程時,內存中的數據會被清空,而磁盤的數據不會,因此,當下次再進入該進程時,該進程仍能夠從diskCache中得到數據,而memoryCache則不行。
類似
diskCache與memoryCache類似之處就是也只能存儲一些派生類資源文件。它的存儲形式爲一個index.dat文件,記錄存儲數據的url,而後再分別存儲該url的response信息和content內容。Response信息最大做用就是用於判斷服務器上該url的content內容是否被修改。
用戶行爲
最後附上一張,用戶行爲影響瀏覽器的緩存行爲。
總結
自此能夠將本文開頭的流程圖理解清楚。
遺留問題
- CDN緩存?
- param: no-cache?
- 分佈式系統 ?
- 負載均衡?
- 緩存資源的存儲與讀取,瀏覽器是以什麼規則去區分memory cache , 仍是disk cache ?
參考文獻
Chrome瀏覽器的緩存文件位置: http://jingyan.baidu.com/article/f3e34a128e41acf5ea653554.html
瀏覽器緩存機制:http://www.cnblogs.com/skynet/archive/2012/11/28/2792503.html
瀏覽器緩存知識小結及應用: http://mp.weixin.qq.com/s/HRrYWnZIWgE_Hawr81CZTw
200 ok 幾種狀態:http://www.cnblogs.com/tangyuu/p/6396644.html