当我们在谈论HTTP缓存时我们在谈论什么
前言
在瀏覽器眾多緩存中的HTTP緩存可能很多人對這個(gè)的概念并沒有很清晰,每個(gè)人都知道進(jìn)入一次網(wǎng)頁之后再刷新一次頁面,加載速度會(huì)比首次加載快非常多,每個(gè)人都知道這是瀏覽器緩存的magic,但是對此背后的原因可能不甚了解...
當(dāng)我們在談?wù)揌TTP緩存時(shí)我們在談?wù)撌裁?
我們實(shí)際上是在談?wù)撓旅孢@兩種情況:
如上圖,瀏覽器對靜態(tài)資源的HTTP緩存有兩種情況,一種是強(qiáng)緩存(本地緩存),另一種是弱緩存(協(xié)商緩存)。
緩存流程:
瀏覽器第一次請求資源時(shí):
瀏覽器第一次請求資源時(shí),必須下載所有的資源,然后根據(jù)響應(yīng)的header內(nèi)容來決定,如何緩存資源。可能采用的是強(qiáng)緩存,也可能是弱緩存
瀏覽器后續(xù)請求資源時(shí)的匹配流程:
由上圖可以知道當(dāng)瀏覽器請求一個(gè)靜態(tài)資源時(shí)的HTTP流程:
強(qiáng)緩存與弱緩存的區(qū)別:
獲取資源形式: 都是從緩存中獲取資源的。
狀態(tài)碼: 強(qiáng)緩存返回200(from cache),弱緩存返回304狀態(tài)碼
請求(最大區(qū)別):
強(qiáng)緩存不發(fā)送請求,直接從緩存中取。
弱緩存需要發(fā)送一個(gè)請求,驗(yàn)證這個(gè)文件是否可以使用(有沒有被改動(dòng)過)。
強(qiáng)緩存:
強(qiáng)緩存是利用Expires或者Cache-Control,讓原始服務(wù)器為文件設(shè)置一個(gè)過期時(shí)間,在多長時(shí)間內(nèi)可以將這些內(nèi)容視為最新的。
若時(shí)間未過期,則命中強(qiáng)緩存,使用緩存文件不發(fā)送請求。
Cache-Control
Cache-Control 是http1.1中為了彌補(bǔ)Expires的缺陷而加入的,當(dāng)Expires和Cache-Control同時(shí)存在時(shí),Cache-Control優(yōu)先級高于Expires。
選項(xiàng):
可緩存性:
public: 表明響應(yīng)可以被任何對象(包括:發(fā)送請求的客戶端,代理服務(wù)器,等等)緩存。
private: 只有用戶自己的瀏覽器能夠進(jìn)行緩存,公共的代理服務(wù)器不允許緩存。
no-cache: 強(qiáng)制瀏覽器在使用cache拷貝之前先提交一個(gè)http請求到源服務(wù)器進(jìn)行確認(rèn)。http請求沒有減少,會(huì)減少一個(gè)響應(yīng)體(文件內(nèi)容),這種個(gè)選項(xiàng)類似弱緩存。
only-if-cached: 表明客戶端只接受已緩存的響應(yīng),并且不要向原始服務(wù)器檢查是否有更新的拷貝。
到期設(shè)置:
max-age=60:設(shè)置緩存存儲(chǔ)的最大周期,超過這個(gè)時(shí)間緩存被認(rèn)為過期(單位秒)。 這里是60秒
其他設(shè)置:
no-store: 告訴瀏覽器在任何情況下都不要進(jìn)行cache,不在本地保留拷貝。
must-revalidate: 緩存必須在使用之前驗(yàn)證舊資源的狀態(tài),并且不可使用過期資源。
更多設(shè)置,移動(dòng)MDN
// 示例 Cache-Control: no-cache, no-store, must-revalidate Cache-Control:public, max-age=31536000 Cache-Control: max-age=3600, must-revalidatehttp1.0時(shí)代的緩存 Expires+Pragma
Expires用于設(shè)置緩存到期時(shí)間:
指定緩存到期GMT的絕對時(shí)間,如果設(shè)了max-age,max-age就會(huì)覆蓋expires,如果expires到期需要重新請求。
Expires:Sat, 09 Jun 2018 08:13:56 GMT有一個(gè)問題是由于使用具體時(shí)間,如果時(shí)間表示出錯(cuò)或者沒有轉(zhuǎn)換到正確的時(shí)區(qū)都可能造成緩存生命周期出錯(cuò)。
Pragma禁用緩存:
Pragma : no-cache 表示防止客戶端緩存,需要強(qiáng)制從服務(wù)器獲取最新的數(shù)據(jù);
Pragma : no-cache //只有這一個(gè)用法 禁用緩存,強(qiáng)制從服務(wù)器獲取最新的數(shù)據(jù);強(qiáng)緩存命中 from memory cache & from disk cache
在測試的時(shí)候,看到命中強(qiáng)緩存時(shí),有兩種狀態(tài),200 (from memory cache) cache & 200 (from disk cache),于是去找了一下這兩者的區(qū)別:
memory cache: 將資源存到內(nèi)存中,從內(nèi)存中獲取。
disk cache:將資源緩存到磁盤中,從磁盤中獲取。
二者最大的區(qū)別在于:當(dāng)退出進(jìn)程時(shí),內(nèi)存中的數(shù)據(jù)會(huì)被清空,而磁盤的數(shù)據(jù)不會(huì)。
更詳細(xì)的介紹推薦這篇文章
弱緩存:
如果強(qiáng)緩存時(shí)間過期,或者沒有設(shè)置,導(dǎo)致未命中的話。就進(jìn)入到了弱緩存的階段了,
Last-Modified & if-modified-since:
Last-Modified與If-Modified-Since是一對報(bào)文頭,屬于http 1.0。
last-modified是web服務(wù)器認(rèn)為文件的最后修改時(shí)間,last-modified是第一次請求文件的時(shí)候,服務(wù)器返回的一個(gè)屬性。
Last-Modified: Sat, 09 Jun 2018 08:13:56 GMT第二次請求這個(gè)文件時(shí),瀏覽器把If-Modified-Since發(fā)送給服務(wù)器,詢問該時(shí)間之后文件是否被修改過。
If-Modified-Since: Sat, 09 Jun 2018 08:13:56 GMT // 跟Last-Modified的值一樣ETag & If-None-Match
ETag與If-None-Match是一對報(bào)文,屬于http 1.1。
ETag是一個(gè)文件的唯一標(biāo)志符。就像一個(gè)哈希或者指紋,每個(gè)文件都有一個(gè)單獨(dú)的標(biāo)志,只要這個(gè)文件發(fā)生了改變,這個(gè)標(biāo)志就會(huì)發(fā)生變化。
ETag機(jī)制類似于樂觀鎖機(jī)制,如果請求報(bào)文的ETag與服務(wù)器的不一致,則表示該資源已經(jīng)被修改過來,需要發(fā)最新的內(nèi)容給瀏覽器。
ETag也是首次請求的時(shí)候,服務(wù)器返回的:
ETag: "8F759D4F67D66A7244638AD249675BE2" // 長這樣If-None-Match也是瀏覽器發(fā)送到服務(wù)器驗(yàn)證,文件是否改變的:
If-None-Match: "8F759D4F67D66A7244638AD249675BE2" // 跟ETag的值一樣Etag/lastModified過程如下:
同時(shí)使用兩個(gè)報(bào)文頭:
同時(shí)使用這兩個(gè)報(bào)文頭,兩個(gè)都匹配才會(huì)命中弱緩存,否則將重新請求資源。
Etag 主要為了解決 Last-Modified 無法解決的一些問題:
用戶操作行為與緩存
F5刷新導(dǎo)致強(qiáng)緩存失效。
ctrl+F5強(qiáng)制刷新頁面強(qiáng)緩存,弱緩存都會(huì)失效。
如何設(shè)置?
一般是服務(wù)器端設(shè)置這些請求頭的,我自己試了用阿里云服務(wù)器設(shè)置Cache-Control,設(shè)置一下很方便的。
嗯,據(jù)說客戶端也是可以設(shè)置強(qiáng)弱緩存,但是找了半天不知道怎么設(shè)置,如果有路過的大佬知道,可以指導(dǎo)一波^_^。
沒有設(shè)置強(qiáng)緩存,返回200
如下圖這種情況,就不太懂怎么回事,下方的解釋也沒看明白,圖片內(nèi)容出自這篇文章
結(jié)語
通過網(wǎng)絡(luò)重復(fù)請求資源既緩慢,成本又高,緩存和重用以前獲取的資源的能力成為優(yōu)化性能很關(guān)鍵的一個(gè)方面,也是大廠面試時(shí)很頻繁出現(xiàn)的內(nèi)容,掌握好這塊知識(shí)點(diǎn)是非常重要的,希望本文能給你帶來些收獲。
總結(jié)
以上是生活随笔為你收集整理的当我们在谈论HTTP缓存时我们在谈论什么的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java高并发之锁优化
- 下一篇: 使用spring boot +WebSo