認(rèn)識(shí)Http的緩存策略

我們?nèi)粘i_發(fā)經(jīng)常和網(wǎng)絡(luò)打交道谢肾,從服務(wù)器上面獲取數(shù)據(jù)。但是如果我們?nèi)绻诙虝r(shí)間內(nèi)多次向服務(wù)器請(qǐng)求的數(shù)據(jù)其實(shí)都是一樣的,我們是沒有必要這么浪費(fèi)用戶的流量的捎谨。為了提高用戶的體驗(yàn),我們需要合理使用緩存憔维,要使用緩存就得搞明白緩存的一些相關(guān)策略機(jī)制涛救,于是就有了這篇文章。

Http的緩存機(jī)制

我們可以先看下面的思維導(dǎo)圖來簡單了解一下Http協(xié)議里面的一些緩存機(jī)制:

導(dǎo)圖.png

正如上圖所示业扒,Http的緩存就僅可用于Get請(qǐng)求检吆。為了方便大家理解上圖,這里我簡單介紹一下一些緩存相關(guān)的重要字段:

Expires:

這個(gè)字段是記錄著緩存的有效期,如Expires:Wed, 26 Jul 2017 13:18:20 GMT.當(dāng)客戶端發(fā)現(xiàn)這個(gè)緩存有效期已經(jīng)過去了,就會(huì)重新向服務(wù)器請(qǐng)求數(shù)據(jù).但是這個(gè)字段存在問題,就是客戶端本地時(shí)間和服務(wù)器端時(shí)間相差過大,就是出現(xiàn)緩存讀取失效的情況.

Cache-Control:

這個(gè)字段是在http1.1之后出現(xiàn)了,用于替代Expires字段的作用.如果Cache-Control:max-age=(X)秒和Expires同時(shí)存在,那么就會(huì)給Cache-Control:max-age(X)秒替代.不過這個(gè)字段并沒有這么簡單程储,它還有其他重要的字段蹭沛,我們來看下面的介紹:
<code>[1] max-age:</code>這個(gè)上面已經(jīng)簡單介紹了一下,這里再具體說明一下:緩存的內(nèi)容將在xxx秒后失效,這個(gè)選項(xiàng)只在HTTP 1.1可用,優(yōu)先級(jí)比Expires高.簡單來說就是判斷緩存內(nèi)容上次訪問時(shí)間是否比這個(gè)max-age要小,小就使用緩存.
<code>[2] no-cache:</code>先不要讀取緩存中的文件,向WEB服務(wù)器請(qǐng)求驗(yàn)證緩存是否新鮮,新鮮則使用緩存
<code>[3] must-revalidate:</code>作用和相同,但是更為嚴(yán)格.每次請(qǐng)求都校驗(yàn)緩存和服務(wù)器源文件,一致就使用緩存,不一致就拿最新
<code>[4] no-store:</code>這個(gè)字段很關(guān)鍵,它表示數(shù)據(jù)不在硬盤中臨時(shí)保存
<code>[5] only-if-cached:</code>就是在客戶端有緩存時(shí)就是用客戶端的緩存,這個(gè)一般都是在無網(wǎng)時(shí)使用
<code>[6] max-stale:</code>只要緩存的時(shí)間沒有超過它(max-stale)指定的時(shí)間,就可以加載使用.我們可以在無網(wǎng)絡(luò)的情況下使用
上面關(guān)于<code>no-cache</code>和<code>must-revalidate</code>的內(nèi)容,我是參考下面這篇文章的:
web性能優(yōu)化之:no-cache與must-revalidate深入探究

Last-Modified / If-Modified-Since

這是需要有緩存存在才能起作用的字段章鲤。
<code>Last-Modified:</code>這個(gè)字段是用來標(biāo)記這個(gè)響應(yīng)資源的最后修改時(shí)間致板。服務(wù)器在響應(yīng)請(qǐng)求時(shí),將會(huì)告訴客戶端這個(gè)響應(yīng)資源的最后修改時(shí)間咏窿,如Last-Modified:Thu, 13 Jul 2017 06:31:05 GMT;

<code>If-Modified-Since:</code>當(dāng)緩存不新鮮時(shí)斟或,發(fā)現(xiàn)緩存具有Last-Modified聲明,服務(wù)器就會(huì)檢查請(qǐng)求頭If-Modified-Since(客戶端緩存頁面數(shù)據(jù)的最后修改時(shí)間)集嵌,服務(wù)器會(huì)把這個(gè)時(shí)間與服務(wù)器上實(shí)際文件的最后修改時(shí)間進(jìn)行比較萝挤。如If-Modified-Since:Mon , 24 Jul 2017 18:53:33 GMT
如果時(shí)間一致,那么返回HTTP狀態(tài)碼304根欧,客戶端接到之后怜珍,就直接把本地緩存文件顯示到屏幕上面。
如果時(shí)間不一致凤粗,就返回HTTP狀態(tài)碼200和新的文件內(nèi)容酥泛,客戶端接到之后,會(huì)丟棄舊文件,把新文件緩存起來并顯示新的內(nèi)容柔袁。

Etag / If-None-Match

這是需要有緩存存在才能起作用的字段呆躲,而且<code>Etag</code>的優(yōu)先級(jí)高于<code>Last-Modified</code>
<code>Etag:</code>這個(gè)字段是請(qǐng)求變量的實(shí)體標(biāo)記捶索。簡單來說就是服務(wù)器響應(yīng)時(shí)給請(qǐng)求URL標(biāo)記插掂,并在HTTP響應(yīng)頭中將其傳送到客戶端進(jìn)行存儲(chǔ)。服務(wù)器端返回的格式如:Etag:“5d8c72a5edda8d6a:3239″.這是通過對(duì)文件的索引節(jié)(INode)大小(Size)和最后修改時(shí)間(MTime)進(jìn)行Hash后得到的數(shù)值;

<code>If-None-Match:</code>上面說了腥例,<code>Etag</code>是服務(wù)器的報(bào)文才有的,那么客戶端需要給服務(wù)器發(fā)送Etag應(yīng)該怎么辦?
就是在http報(bào)文里面使用If-None-Match這個(gè)字段來存放Etag的值.服務(wù)器收到請(qǐng)求后發(fā)現(xiàn)有If-None-Match則與被請(qǐng)求資源的相應(yīng)校驗(yàn)串進(jìn)行比對(duì),之后才決定返回200304.如:If-None-Match:"5d8c72a5edda8d6a:3239"

Etag 和 Last-Modified

到這里我們會(huì)發(fā)現(xiàn)一件事辅甥,就是<code>Last-Modified</code>和<code>Etag</code>的功能居然是重復(fù)的,這就奇怪了燎竖。既然使用<code>Last-Modified</code>已經(jīng)足以讓客戶端知道本地的緩存副本是否足夠新璃弄,為什么還需要<code>Etag</code>呢?其實(shí)還是有原因的,因?yàn)?lt;code>Last-Modified</code>有下面幾個(gè)問題難以解決:
1.<code>Last-Modified</code>標(biāo)注的最后修改只能精確到秒級(jí)构回,如果某些文件在1秒鐘以內(nèi)被修改多次的話谢揪,它將不能準(zhǔn)確標(biāo)注文件的修改時(shí)間
2.如果某些文件會(huì)被定期生成,當(dāng)有時(shí)內(nèi)容并沒有任何變化捐凭,但<code>Last-Modified</code>卻改變了拨扶,導(dǎo)致文件沒法使用緩存
3.有可能存在服務(wù)器沒有準(zhǔn)確獲取文件修改時(shí)間或者與代理服務(wù)器時(shí)間不一致等情形
<code>Etag</code>是服務(wù)器自動(dòng)生成或者由開發(fā)者生成的對(duì)應(yīng)資源在服務(wù)器端的唯一標(biāo)識(shí)符,能夠更加準(zhǔn)確的控制緩存;<code>Last-Modified</code>與<code>ETag</code>是可以一起使用的,服務(wù)器會(huì)優(yōu)先驗(yàn)證<code>ETag</code>诽俯,一致的情況下轧苫,才會(huì)繼續(xù)比對(duì)<code>Last-Modified</code>,最后才決定是否返回304200.

通過okhttp的cache設(shè)置來加深理解

我們現(xiàn)在已經(jīng)了解了部分Http的緩存策略,下面我們來通過代碼來加深了解吧。本人比較喜歡okhttp,所以下面的代碼都是用它來弄了印蓖。

public void click(View view) {
        int maxCacheSize = 10 * 1024 * 1024;
        //設(shè)置緩存路徑
        Cache cache = new Cache(getCacheDir(), maxCacheSize);
        OkHttpClient client = new OkHttpClient.Builder()
                //設(shè)置緩存
                .cache(cache)
                .build();
        Request request = new Request.Builder()
                .url("http://www.qq.com/")
                .build();
       
        client.newCall(request).enqueue(new Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
               Log.w(TAG, "start");
                Log.w(TAG, "response cache :" + response.cacheResponse());
                Log.w(TAG, "response network :" + response.networkResponse());
                response.body().close();
            }
            @Override
            public void onFailure(Call call, IOException e) {

            }
        });
    }

我們先來看下qq官網(wǎng)的Cache-Control:

image.png

可以看到max-age=60,說明本地緩存在60秒內(nèi)都是新鮮的京腥,那么我們就連續(xù)兩次訪問qq官網(wǎng)來看下Log吧:

image.png

從打印中赦肃,我們可以看出第一次訪問我們是從服務(wù)器中獲取最新的數(shù)據(jù);但是第二次訪問時(shí)公浪,就直接使用本地緩存了他宛,畢竟兩次請(qǐng)求相隔時(shí)間最多才1秒。那么okhttp緩存到本地時(shí)欠气,數(shù)據(jù)是以什么格式保存的呢?這里我是將緩存保存在內(nèi)部存儲(chǔ)里的:

image.png

為了滿足好奇心厅各,這里我們來逐一來看下:

7f4c79817fabaeaa0e909754cfe655e7.0里面的內(nèi)容
7f4c79817fabaeaa0e909754cfe655e7.1里面的內(nèi)容
journal里面的內(nèi)容

原來這3個(gè)文件分別是請(qǐng)求的header,加密的response和每一條reponse讀寫操作狀態(tài)記錄预柒。
ok队塘,我們接著來測試袁梗,這次換簡書的官網(wǎng)來測試,先看下簡書官網(wǎng)的一些header信息:

image.png

max-age=0說明緩存有效時(shí)間為0秒憔古,但是設(shè)置了Etag校驗(yàn)緩存遮怜,我們看下請(qǐng)求打印的Log吧:

image.png

我們重點(diǎn)看第二次訪問的Log,okhttp的cacheResponse可用投放,而且它的networkResponse返回的http碼為304,說明了本地緩存是可用的适贸。
那么灸芳,有什么網(wǎng)站是不支持緩存嗎?當(dāng)然有了拜姿,知乎是一個(gè)很有名氣的網(wǎng)站烙样,它就不支持客戶端使用緩存:

image.png

它已經(jīng)在Cache-Control里面設(shè)置不支持硬盤存儲(chǔ)的no-store字段了,我們看下運(yùn)行的Log:

訪問知乎的結(jié)果

可以看到蕊肥,我們已經(jīng)多次重新訪問知乎的首頁了谒获,但是每次都只能重新向服務(wù)器拿最新的數(shù)據(jù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末壁却,一起剝皮案震驚了整個(gè)濱河市批狱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌展东,老刑警劉巖赔硫,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盐肃,居然都是意外死亡爪膊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門砸王,熙熙樓的掌柜王于貴愁眉苦臉地迎上來推盛,“玉大人,你說我怎么就攤上這事谦铃≡懦桑” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵驹闰,是天一觀的道長凿跳。 經(jīng)常有香客問我,道長疮方,這世上最難降的妖魔是什么控嗜? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮骡显,結(jié)果婚禮上疆栏,老公的妹妹穿的比我還像新娘曾掂。我一直安慰自己,他們只是感情好壁顶,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布珠洗。 她就那樣靜靜地躺著,像睡著了一般若专。 火紅的嫁衣襯著肌膚如雪许蓖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天调衰,我揣著相機(jī)與錄音膊爪,去河邊找鬼。 笑死嚎莉,一個(gè)胖子當(dāng)著我的面吹牛米酬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播趋箩,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼赃额,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了叫确?” 一聲冷哼從身側(cè)響起跳芳,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎竹勉,沒想到半個(gè)月后筛严,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饶米,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年桨啃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片檬输。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡照瘾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丧慈,到底是詐尸還是另有隱情析命,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布逃默,位于F島的核電站鹃愤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏完域。R本人自食惡果不足惜软吐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吟税。 院中可真熱鬧凹耙,春花似錦姿现、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至意述,卻和暖如春提佣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荤崇。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工拌屏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人天试。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓槐壳,卻偏偏與公主長得像然低,于是被迫代替她去往敵國和親喜每。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 本文內(nèi)容大多參考《圖解HTTP》一書 一. 認(rèn)識(shí)代理服務(wù)器 所以講緩存為什么要先扯代理服務(wù)器雳攘?別急带兜,讓我們看一下一...
    流光號(hào)船長閱讀 1,937評(píng)論 0 10
  • 淺談瀏覽器Http的緩存機(jī)制 ? ? ? ? ? ? ? ? 針對(duì)瀏覽器的http緩存的分析也算是老生常談了,每隔...
    meng_philip123閱讀 1,009評(píng)論 0 10
  • 針對(duì)瀏覽器的http緩存的分析也算是老生常談了吨灭,每隔一段時(shí)間就會(huì)冒出一篇不錯(cuò)的文章刚照,其原理也是各大公司面試時(shí)幾乎必...
    全端玩法閱讀 879評(píng)論 0 9
  • 針對(duì)瀏覽器的http緩存的分析也算是老生常談了,每隔一段時(shí)間就會(huì)冒出一篇不錯(cuò)的文章喧兄,其原理也是各大公司面試時(shí)幾乎必...
    單純的土豆閱讀 391評(píng)論 0 2
  • 網(wǎng)絡(luò)特有的延遲以及數(shù)據(jù)傳輸?shù)某杀疚夼希萍s互聯(lián)網(wǎng)快速獲取Web資源。為此吠冤,HTTP協(xié)議引入緩存以空間換時(shí)間浑彰,使瀏覽器緩...
    大頭8086閱讀 3,070評(píng)論 2 12