Web緩存分析

前言

不論是在移動(dòng)端還是前端,web緩存(Http緩存)都是很重要的一部分。在移動(dòng)端,對(duì)于用戶流量控制的優(yōu)化,web緩存就起到了決定性的作用。最開(kāi)始接觸這塊是在使用OkHttp的攔截器修改Http請(qǐng)求頭進(jìn)行web緩存,后來(lái)仔細(xì)研究了一下這塊。而Web緩存就是客戶端和服務(wù)端之間通過(guò)一種約束,通過(guò)新鮮度校驗(yàn)來(lái)給客戶端提供緩存資源。

Web緩存的好處

  • 緩存可以減少手機(jī)流量的消耗
  • 可以更快的響應(yīng)用戶的操作,提升用戶體驗(yàn)度
  • 降低資源服務(wù)器的壓力,減少并發(fā)量

Web緩存的分類(lèi)

  • 手機(jī)文件緩存

    由于移動(dòng)端不像前端,前端開(kāi)發(fā)中瀏覽器都默認(rèn)實(shí)現(xiàn)了Web緩存,所以我們可以通過(guò)請(qǐng)求頭的控制來(lái)讓瀏覽器自動(dòng)為我們進(jìn)行緩存。但是移動(dòng)端沒(méi)有這種默認(rèn)實(shí)現(xiàn)Web緩存的容器,所以需要我們自己手動(dòng)通過(guò)文件緩存網(wǎng)絡(luò)請(qǐng)求過(guò)來(lái)的報(bào)文。Okhttp或者結(jié)合Retrofit(一樣)都是可以通過(guò)OkhttpClient添加一個(gè)構(gòu)造好的Cache實(shí)例,其中Cache實(shí)例我們需要指定文件路徑和大小。具體可以看我這個(gè)代碼Demo。

  • CDN緩存(內(nèi)容分發(fā)網(wǎng)關(guān)緩存)

    實(shí)際上是網(wǎng)關(guān)緩存的一種,而網(wǎng)關(guān)緩存又叫反向代理緩存(提前接受客戶端發(fā)來(lái)的原始請(qǐng)求,然后進(jìn)行按需請(qǐng)求分配)。CDN緩存一般是由網(wǎng)站管理員自己部署,為了讓他們的網(wǎng)站更容易擴(kuò)展并獲得更好的性能。通常情況下,瀏覽器先向CDN網(wǎng)關(guān)發(fā)起Web請(qǐng)求,網(wǎng)關(guān)服務(wù)器后面對(duì)應(yīng)著一臺(tái)或多臺(tái)負(fù)載均衡源服務(wù)器,會(huì)根據(jù)它們的負(fù)載請(qǐng)求,動(dòng)態(tài)將請(qǐng)求轉(zhuǎn)發(fā)到合適的源服務(wù)器上。從瀏覽器角度來(lái)看,整個(gè)CDN就是一個(gè)源服務(wù)器,從這個(gè)層面來(lái)說(shuō),瀏覽器和服務(wù)器之間的緩存機(jī)制,在這種架構(gòu)下同樣適用。

  • 代理服務(wù)器緩存

    代理服務(wù)器是一種處在客戶端和服務(wù)端中間的服務(wù)器,處在兩者之間的網(wǎng)絡(luò)之中。代理服務(wù)器以共享緩存的方式保存著報(bào)文副本,可以減少客戶端到原始服務(wù)器的長(zhǎng)距離請(qǐng)求。自然訪問(wèn)同一種報(bào)文副本的用戶越多,代理服務(wù)器的利用率越高,緩存的命中率也越高。

  • 數(shù)據(jù)庫(kù)緩存

    這是后臺(tái)開(kāi)發(fā)的時(shí)候,緩存從數(shù)據(jù)庫(kù)中查找的數(shù)據(jù),減少數(shù)據(jù)庫(kù)的并發(fā)(比如NoSQL)。

共有緩存和私有緩存

  • 共有緩存(Cache-Control: public):這種緩存常見(jiàn)的就是代理緩存,意思就是一個(gè)用戶群體都可以訪問(wèn)這個(gè)緩存服務(wù)器,這個(gè)緩存服務(wù)器緩存了所有群體的報(bào)文緩存
  • 私有緩存(Cache-Control: private):這種緩存常見(jiàn)的就是文件緩存(本地緩存),只允許一個(gè)用戶個(gè)體去訪問(wèn)。

Web緩存的層次結(jié)構(gòu)

一般來(lái)說(shuō),安卓中的圖片多級(jí)緩存和這個(gè)概念不大相同,這里的多級(jí)緩存的意思是在客戶端和服務(wù)端之間部署多級(jí)緩存。常見(jiàn)部署如下:

  • 手機(jī)文件緩存(瀏覽器緩存): 一級(jí)緩存
  • 小型的局域網(wǎng)內(nèi)緩存:二級(jí)緩存,小型的,代價(jià)小,容量小的緩存代理
  • 大型的廣域網(wǎng)內(nèi)緩存:三級(jí)緩存 ,大型的,代價(jià)高,容量大的緩存代理

Web緩存的流程

先上張圖:

web.png
  1. 在客戶端發(fā)起一次請(qǐng)求的時(shí)候,首先一層一層的緩存會(huì)根據(jù)算法判斷緩存中是否存在文檔副本,如果不存在的話就會(huì)像資源服務(wù)器或者父代理緩存服務(wù)器(上一級(jí)緩存服務(wù)器)繼續(xù)請(qǐng)求客戶端需要的資源。
  2. 如果資源副本存在的話就會(huì)根據(jù)資源的元數(shù)據(jù)(記錄資源在緩存中保存了多長(zhǎng)時(shí)間以及它被用了多少次)來(lái)計(jì)算資源的新鮮度,如果資源新鮮的話就直接返回給客戶端。
  3. 如果不新鮮的話,會(huì)判斷資源在緩存中的副本和在資源服務(wù)器里面的文本副本是否一致,如果一致表示資源未發(fā)生改變,那么仍然還是由緩存返回。
  4. 如果資源發(fā)生改變,那么由資源服務(wù)器來(lái)返回資源給客戶端,并且用這份資源存入緩存中。

大致流程就是這樣,請(qǐng)求-檢驗(yàn)-在驗(yàn)證,下面對(duì)于過(guò)程的細(xì)節(jié)詳細(xì)說(shuō)說(shuō):

文檔過(guò)期的判斷

緩存數(shù)據(jù)是否過(guò)期是由數(shù)據(jù)的使用期和過(guò)期日期共同決定的。

  • 過(guò)期時(shí)期(新鮮生存期)

    過(guò)期時(shí)期可以通過(guò)Cache-Control的max-age和max-stale或者Expires來(lái)設(shè)置。其中,Cache-Control中指定的是相對(duì)時(shí)間,而Expries指定的是數(shù)據(jù)過(guò)期的絕對(duì)時(shí)間。但是資源服務(wù)器的時(shí)間經(jīng)常會(huì)出現(xiàn)與客戶端不同步的情況(我就遇到過(guò)這種坑。。)所以用相對(duì)時(shí)間更加合理,并且Cache-Control的優(yōu)先級(jí)要高于Expries。

Cache-Control: max-stale = <s> 在指定的秒數(shù)里面緩存可以提供過(guò)期了的數(shù)據(jù)
Cache-Control: max-age = <s> 在指定的秒數(shù)里面,緩存里面的數(shù)據(jù)不會(huì)過(guò)期
Cache-Control: min-fresh = <s> 至少在未來(lái)數(shù)秒內(nèi)數(shù)據(jù)要保持新鮮
Cache-Control: private or public 私有緩存或者共有緩存
Cache-Control: no-cache 提供數(shù)據(jù)之前必去要去和資源服務(wù)器的數(shù)據(jù)進(jìn)行比對(duì)判斷數(shù)據(jù)是否更新
Cache-Control: no-store 禁止一切緩存
Cache-Control: must-revalidate 告訴緩存,必須嚴(yán)格遵循服務(wù)器的規(guī)定,驗(yàn)證之后才能提供過(guò)期的數(shù)據(jù)
Cache-Contero: only-if-cached 只有當(dāng)緩存中有副本的時(shí)候,客戶端才能獲取一份數(shù)據(jù)副本

需要注意的是

  1. no-cache 不是不使用緩存而是必須比對(duì)了之后才能提供,no-store才是完全禁止緩存
  2. 優(yōu)先級(jí):no-staore>no-cache>must-revalidate>max-age>Exprise

在移動(dòng)端的開(kāi)發(fā)中,如何控制我們的數(shù)據(jù)緩存過(guò)期時(shí)間需要移動(dòng)端和后臺(tái)共同商量之后得出一套方案,比如像數(shù)據(jù)不停變換更新的并且數(shù)據(jù)量不大的,應(yīng)該禁用緩存以保證數(shù)據(jù)的及時(shí)性,像周刊,課表這種長(zhǎng)期不變的數(shù)據(jù)應(yīng)該添加上合理的緩存時(shí)間。

  • 使用時(shí)間

    所謂使用時(shí)間就是數(shù)據(jù)從資源服務(wù)器發(fā)出之后,到被客戶端收到,一共經(jīng)歷了多久。但是使用時(shí)期并不容易計(jì)算。因?yàn)榉?wù)器,代理,客戶端之間時(shí)間不同步,網(wǎng)絡(luò)延時(shí),網(wǎng)絡(luò)傳輸耗時(shí)等等都會(huì)造成使用時(shí)期難以計(jì)算。

    1.直接通過(guò)Date首部進(jìn)行計(jì)算

    ? 這種計(jì)算方式我就被坑過(guò),之前直接設(shè)置max-age=3600(一分鐘)發(fā)現(xiàn)一點(diǎn)緩存效果都沒(méi)有。我發(fā)現(xiàn)響應(yīng)頭的Date首部與現(xiàn)在時(shí)間不同,慢了好幾天。首先要理解Date首部,Date首部是服務(wù)器發(fā)出相應(yīng)的時(shí)間,并且是服務(wù)器的絕對(duì)時(shí)間,并且Date首部只能是資源服務(wù)器設(shè)置,代理和緩存都不能修改,時(shí)間的描述格式由RFC822定義,所以如果時(shí)間不同步的話,直接用客戶端時(shí)間減去Date來(lái)計(jì)算使用期是行不通的。

    2.通過(guò)Age首部進(jìn)行計(jì)算

    Age首部只適用于HTTP/1.1的設(shè)備,Age表示數(shù)據(jù)從產(chǎn)生到現(xiàn)在經(jīng)過(guò)了多長(zhǎng)時(shí)間,是個(gè)相對(duì)時(shí)間

    通過(guò)Age首部,我們可以累加資源在各個(gè)代理中存在的時(shí)間,加上數(shù)據(jù)從資源服務(wù)器到緩存的網(wǎng)絡(luò)傳輸時(shí)間(一般用緩存到服務(wù)器,服務(wù)器到緩存雙向的傳輸時(shí)間來(lái)保守估計(jì))。

    所以我們可以看出,完整的使用時(shí)期計(jì)算應(yīng)該是如下圖:

web2.png

可以看出其實(shí)是忽略了客戶端到緩存的網(wǎng)絡(luò)傳輸時(shí)間,多算了緩存到資源服務(wù)器的網(wǎng)絡(luò)傳輸時(shí)間。

再驗(yàn)證

如果第一次緩存未命中的話,就會(huì)進(jìn)行服務(wù)器再驗(yàn)證。用來(lái)判斷服務(wù)器的資源是否發(fā)生改變。

If-Modified-Since與Last-Modified(基于Date的再驗(yàn)證)

If-Modified-Since是請(qǐng)求字段,值為一個(gè)絕對(duì)時(shí)間,用于通知服務(wù)器在這個(gè)時(shí)間之前,默認(rèn)資源是未被修改的(不去進(jìn)行再驗(yàn)證),如果超過(guò)了這個(gè)時(shí)間,就會(huì)將這個(gè)時(shí)間和資源最后修改的時(shí)間進(jìn)行對(duì)比,如果小于資源最后修改的時(shí)間,那么Last-Modified響應(yīng)首部會(huì)返回資源最后被修改的時(shí)間,并且返回200.如果大于最后修改的時(shí)間,那么Last-Modified響應(yīng)首部會(huì)返回304表示資源未被修改。

If-None-Match和ETag(基于實(shí)體標(biāo)簽的再驗(yàn)證)

ETag可以看作是資源的版本號(hào),并且在強(qiáng)驗(yàn)證器下,資源發(fā)生細(xì)微的變化都會(huì)導(dǎo)致ETag的變化,在弱驗(yàn)證器下,資源發(fā)生細(xì)微的變化都不會(huì)導(dǎo)致ETag的變化,這個(gè)“細(xì)微”度量標(biāo)準(zhǔn)是由后臺(tái)開(kāi)發(fā)人員來(lái)確定的??蛻舳丝梢愿鶕?jù)If-Modified-Since來(lái)添加你現(xiàn)在所擁有的ETag版本號(hào),發(fā)送給服務(wù)器,然后服務(wù)器進(jìn)行比較。如果版本號(hào)不同,那么就會(huì)返回200,并且將最新的ETag值添加到ETag響應(yīng)頭里面。如果相同,返回304。
兩者之間并沒(méi)有優(yōu)先級(jí)之分,如果同時(shí)存在,那么客戶端和服務(wù)端應(yīng)該將兩者綜合起來(lái)考量。

未經(jīng)博主同意,不得轉(zhuǎn)載該篇文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本篇文章篇幅比較長(zhǎng),先來(lái)個(gè)思維導(dǎo)圖預(yù)覽一下。 一、概述 1.計(jì)算機(jī)網(wǎng)絡(luò)體系結(jié)構(gòu)分層 2.TCP/IP 通信傳輸流 ...
    滌生_Woo閱讀 56,201評(píng)論 24 557
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評(píng)論 19 139
  • 本文是《圖解HTTP》讀書(shū)筆記的第二篇,主要包括此書(shū)的第六章內(nèi)容,因?yàn)榈诹碌膬?nèi)容較多,而且比較重要,所以單獨(dú)寫(xiě)為...
    lijiankun24閱讀 1,499評(píng)論 0 6
  • 1. 網(wǎng)絡(luò)基礎(chǔ)TCP/IP HTTP基于TCP/IP協(xié)議族,HTTP屬于它內(nèi)部的一個(gè)子集。 把互聯(lián)網(wǎng)相關(guān)聯(lián)的協(xié)議集...
    yozosann閱讀 3,606評(píng)論 0 20
  • 在知識(shí)變現(xiàn)如此多元化的今天,掌握學(xué)習(xí)方法,能讓你在人群中快速脫穎而出。身為普通人的我們,學(xué)習(xí)就成了一門(mén)非常重要的技...
    陶壹閱讀 151評(píng)論 0 0

友情鏈接更多精彩內(nèi)容