自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

HTTP緩存協(xié)議實戰(zhàn)

網(wǎng)絡(luò) 無線技術(shù)
做為客戶端開發(fā),經(jīng)常出現(xiàn)一些與cache相關(guān)的問題在排查時無從下手,通過學習了解這部分內(nèi)容,可以幫助快速的分析定位這部分問題。

一、什么是緩存

緩存,又稱作Cache,我們把臨時存儲數(shù)據(jù)的地方叫做緩存池,緩存池里面放的數(shù)據(jù)就叫做緩存。當用戶需要使用這些數(shù)據(jù),首先在緩存中尋找,如果找到了則直接使用。如果找不到,則再去其他數(shù)據(jù)源中查找。

二、為什么要使用緩存技術(shù)

緩存的本質(zhì)就是用空間換時間,以臨時存儲的數(shù)據(jù)暫時代替數(shù)據(jù)源中讀取最新的數(shù)據(jù),這種方式帶來的好處在不同的場景下是不一樣的。

舉個例子:

當我們需要喝水時,我們會拿出一個水杯,去水龍頭接一杯水來喝。大家可以思考一下,為什么用杯子來喝水,而不是直接用嘴巴在水龍頭接水喝。

用杯子喝水確實存在一些既有的問題,比如杯子里面的水容易變涼,而水龍頭流出的水確是恒溫的。我們可以想象一下,公司里的同事們排隊在水龍頭下面喝水的場面,確實有點滑稽,我們寧愿接受杯子里的水會變涼這個既有問題。

用杯子喝水有以下幾個優(yōu)勢:

  • 用杯子喝水解決了總是要去找水龍頭的問題,因為杯子可以一次接更多的水。
  • 用杯子喝水更不容易灑出來,不容易浪費水。
  • 用杯子喝水比趴在水龍頭下喝水更優(yōu)雅。

我們把杯子看成一個緩存池,杯中的水看成緩存,我們接受了杯中水會變涼的問題,相當于犧牲了數(shù)據(jù)的實時性。把這些優(yōu)勢換一個方式來描述,于是使用緩存的優(yōu)勢變成了下面幾個:

  • 降低了系統(tǒng)壓力;
  • 節(jié)省了資源消耗;
  • 優(yōu)化用戶體驗。

三、HTTP緩存的作用

網(wǎng)絡(luò)的其中一個特點就是不穩(wěn)定性,很多用戶受到網(wǎng)速慢的困擾。

服務(wù)器在大量用戶訪問的場景下實時計算數(shù)據(jù)也很容易產(chǎn)生瓶頸,導致服務(wù)變慢。從緩存技術(shù)具備的優(yōu)勢來看,很適合解決網(wǎng)絡(luò)服務(wù)不穩(wěn)定的問題。

四、HTTP緩存協(xié)議

協(xié)議是溝通過程中雙方都遵守并且使用的一種規(guī)則。舉個栗子,客戶端和服務(wù)器兩位大兄弟在新款機型問題上進行了幾次溝通?

  • 客戶端:大哥,新款nex發(fā)布沒?
  • 服務(wù)器:老弟,還沒發(fā),你記住,別老來問我!

一周后......

  • 客戶端:大哥,我又來了,最新情況如何?
  • 服務(wù)器:跟上次一樣。

一個月后.....

  • 客戶端:大哥,這都一個月了,怎么樣了啊?!
  • 服務(wù)器:已經(jīng)開售啦!

在這個例子里面,客戶端與服務(wù)端溝通過程中就遵循某種規(guī)則,我們來看一下:

  • 數(shù)據(jù)部分:機型的內(nèi)容;
  • 協(xié)議部分:1)別老來問我,2)最新情況如何,3)跟上次一樣。

服務(wù)端說的這些話,客戶端都能看懂并且明白這些話中所蘊含的意義,這就是客戶端與服務(wù)端之間達成的某種通訊協(xié)議。

4.1 HTTP消息頭

在介紹HTTP緩存協(xié)議之前,我們先來了解一下HTTP消息頭的基礎(chǔ)知識。我們對HTTP/HTTPS的數(shù)據(jù)請求都比較熟悉,在HTTP的數(shù)據(jù)請求中有一種信息叫做“頭部信息”。

頭部信息是在客戶端請求或者服務(wù)端響應(yīng)是傳遞給對方的一種信息。我們來看一下HTTP協(xié)議的組成部分。

  • HTTP 請求的組成:狀態(tài)行、請求頭、消息主體三部分組成。
  • HTTP 響應(yīng)的組成:狀態(tài)行、響應(yīng)頭、響應(yīng)正文。

其中,請求頭和響應(yīng)頭就是我們這里說的“頭部信息”或者又叫“消息頭”。那么頭部信息有什么作用呢?

4.2 請求頭

如圖所示:

4.3 響應(yīng)頭

如圖所示:

我們今天要講的緩存協(xié)議——Cache-Control, 也是放在消息頭中進行控制的。

4.4 緩存協(xié)議

在第一節(jié)中,我們介紹了使用緩存技術(shù)的三個優(yōu)勢,在網(wǎng)絡(luò)數(shù)據(jù)交換的過程中,使用緩存技術(shù)同樣有這三個優(yōu)勢。

(1)降低系統(tǒng)壓力

使用HTTP緩存技術(shù),可以有效的降低服務(wù)端的壓力,服務(wù)端不需要實時計算數(shù)據(jù)并返回數(shù)據(jù)。

(2)節(jié)省資源消耗

使用HTTP緩存技術(shù),可以有效的避免大量的重復數(shù)據(jù)傳輸,降低流量消耗。

(3)優(yōu)化用戶體驗

使用HTTP緩存技術(shù),本地緩存可以以較快的速度加載,減少用戶等待時間。

在講HTTP協(xié)議如何實現(xiàn)緩存之前,我們先來講一下緩存類型。HTTP緩存一般被分為兩類,私有緩存和共享緩存。

4.4.1 私有緩存

緩存被存儲在設(shè)備本地或者獨立的賬戶體系下,僅供當前用戶使用,他可以用來降低服務(wù)器壓力,提高用戶體驗,甚至實現(xiàn)離線瀏覽。

4.4.2 共享緩存

共享緩存是在代理服務(wù)器或者其他中間服務(wù)器中進行二次緩存的數(shù)據(jù),一般這里我們常見的是CDN,這種緩存可以被多個用戶訪問,用來減少流量和延遲。

對于一次網(wǎng)絡(luò)數(shù)據(jù)交互,本地緩存和共享緩存可以同時存在,HTTP協(xié)議中規(guī)定了如何進行控制這些緩存的使用和更新。在HTTP中,控制緩存有兩種字段:一個是Pragma;另一個是cache-control。

Pragma 是一個在 HTTP/1.0 中定義的字段,從mozilla官網(wǎng)文檔上查詢,Pragma 支持現(xiàn)有的幾乎所有瀏覽器。

但是作為舊時代的產(chǎn)物,cache-control正在逐步的替代它。cache-control 是從 HTTP/1.1開始引入的協(xié)議。有些前端開發(fā)者會選擇在cache-control的基礎(chǔ)上增加Pragma 來向下兼容,事實上android的webview即支持Pragma 又支持cache-control。

而當Pragma 和 cache-control 同時出現(xiàn)時,Pragma 的優(yōu)先級大于cache-control 當然,這不是今天的重點,有興趣的同學可以自行查閱相關(guān)資料。

下面我們就具體的來講一下cache-control緩存協(xié)議的具體定義。HTTP協(xié)議規(guī)定,服務(wù)端通過響應(yīng)頭中的cache-control將緩存方式通知給客戶端,同時客戶端也可以通過請求頭中的cache-control來將自己的緩存需求通知給服務(wù)器。

4.4.3 響應(yīng)頭中的cache-control

響應(yīng)頭中的cache-control一般有如下取值:

  • Cache-control: public
  • Cache-control: private
  • Cache-control: no-cache
  • Cache-control: no-store
  • Cache-control: no-transform
  • Cache-control: must-revalidate
  • Cache-control: proxy-revalidate
  • Cache-Control: max-age=
  • Cache-control: s-maxage=

4.4.4 請求頭中的cache-control

請求頭中的cache-control一般有如下取值:

  • Cache-Control: max-age=
  • Cache-Control: max-stale[=]
  • Cache-Control: min-fresh=
  • Cache-control: no-cache
  • Cache-control: no-store
  • Cache-control: no-transform
  • Cache-control: only-if-cached

mozilla開發(fā)者網(wǎng)站將這些取值分為如下幾個類別進行描述。

4.4.5 可緩存性控制

(1) public

表明響應(yīng)可以被任何對象(包括:發(fā)送請求的客戶端,代理服務(wù)器,等等)緩存,即使是通常不可緩存的內(nèi)容。例如:

  • 該響應(yīng)沒有max-age指令或Expires消息頭;
  • 該響應(yīng)對應(yīng)的請求方法是 POST 。

(2) private

表明響應(yīng)只能被單個用戶緩存,不能作為共享緩存(即代理服務(wù)器不能緩存它)。私有緩存可以緩存響應(yīng)內(nèi)容,比如:對應(yīng)用戶的本地瀏覽器。

(3) no-cache

在發(fā)布緩存副本之前,強制要求緩存把請求提交給原始服務(wù)器進行驗證(協(xié)商緩存驗證)。

(4) no-store

緩存不應(yīng)存儲有關(guān)客戶端請求或服務(wù)器響應(yīng)的任何內(nèi)容,即不使用任何緩存。

4.4.6 緩存有效性控制

(1) max-age=

設(shè)置緩存存儲的最大周期,超過這個時間緩存被認為過期(單位秒)。與Expires相反,時間是相對于請求的時間。

(2) s-maxage=

覆蓋max-age或者Expires頭,但是僅適用于共享緩存(比如各個代理),私有緩存會忽略它。

(3) max-stale[=]

表明客戶端愿意接收一個已經(jīng)過期的資源??梢栽O(shè)置一個可選的秒數(shù),表示響應(yīng)不能已經(jīng)過時超過該給定的時間。

(4) min-fresh=

表示客戶端希望獲取一個能在指定的秒數(shù)內(nèi)保持其最新狀態(tài)的響應(yīng)。

(5) stale-while-revalidate=

表明客戶端愿意接受陳舊的響應(yīng),同時在后臺異步檢查新的響應(yīng)。秒值指示客戶愿意接受陳舊響應(yīng)的時間長度。

(6) stale-if-error=

表示如果新的檢查失敗,則客戶愿意接受陳舊的響應(yīng)。秒數(shù)值表示客戶在初始到期后愿意接受陳舊響應(yīng)的時間。

4.4.7 重新驗證和重新加載

(1) must-revalidate

一旦資源過期(比如已經(jīng)超過max-age),在成功向原始服務(wù)器驗證之前,緩存不能用該資源響應(yīng)后續(xù)請求。

(2) proxy-revalidate

與must-revalidate作用相同,但它僅適用于共享緩存(例如代理),并被私有緩存忽略。

4.4.8 其他控制

(1) no-transform

不得對資源進行轉(zhuǎn)換或轉(zhuǎn)變。Content-Encoding、Content-Range、Content-Type等HTTP頭不能由代理修改。例如,非透明代理或者如Google's Light Mode可能對圖像格式進行轉(zhuǎn)換,以便節(jié)省緩存空間或者減少緩慢鏈路上的流量。no-transform指令不允許這樣做。

(2) only-if-cached

表明客戶端只接受已緩存的響應(yīng),并且不要向原始服務(wù)器檢查是否有更新的拷貝。

從這些描述以及分類中可以看出來,可緩存性控制+緩存有效性控制+其他控制 ,這幾個控制維度是不沖突的,可以共同實現(xiàn)緩存的實現(xiàn)方式限定。

事實上cache-control確實是可以同時接受多個取值的,多個不同的指令可以搭配使用來對緩存進行控制。如果使用了相矛盾的多個指令取值,那么指令就會按照優(yōu)先級進行緩存控制。

比如no-store和max-age這兩種在行為上矛盾的指令取值放在一起下發(fā),那么終端就只會按照no-store來進行緩存。

4.4.9 協(xié)議工作實戰(zhàn)分析

專業(yè)的運維人員,一定很了解這些描述所表達的意思。然而作為客戶端或者前端的我們,光是看這些專業(yè)術(shù)語,可能很難理解不同配置取值下實際的緩存效果。

因此為了搞明白取值對實際緩存效果的影響。我使用兩臺電腦,分別搭建了一個靜態(tài)資源服務(wù)器(源服務(wù)器),一個代理服務(wù)器,通過模擬線上服務(wù)器的場景,來對常見的幾種緩存控制模式進行驗證。nginx的安裝比較簡單,此處不在贅述。

(1) 靜態(tài)資源服務(wù)器(源服務(wù)器)

windows+nginx,配置如下:

(2) 代理服務(wù)器

windows+nginx,配置如下:

服務(wù)器搭建完成后,我們逐個改變cache-control的取值,來模擬幾種常見的緩存控制模式,來幫助大家理解這些取值,加深印象。在日常的使用過程中,cache-control更多的是被放在響應(yīng)頭中來控制瀏覽的緩存行為,因此我們先來驗證一下cache-control放在響應(yīng)頭中的情況。

場景:靜態(tài)資源服務(wù)器(源服務(wù)器)的響應(yīng)頭中沒有添加任何cache-control標識。沒有添加標識,其實對應(yīng)的就是public標識。

public通常可以看成默認值,如果我們不在響應(yīng)中添加任何有關(guān)Cache-control的header,那么這次響應(yīng)默認的處理邏輯就類似Cache-control:public。

(這里使用"通常","類似"這種不確定的字眼,需要解釋一下,如果服務(wù)器返回了302或者307這種重定向響應(yīng)時,添加Cache-control:public會讓瀏覽器把重定向響應(yīng)也緩存起來,但是如果不添加Cache-control,則不會緩存,也存在不同網(wǎng)絡(luò)框架或者瀏覽器做不同處理的可能性)。

public的意思是瀏覽器或者代理服務(wù)器都可以對靜態(tài)資源服務(wù)器(源服務(wù)器)返回的資源進行緩存。使用瀏覽器直接訪問靜態(tài)資源服務(wù)器(不經(jīng)過代理服務(wù)器)。

(3) 第一次訪問

第一次訪問,服務(wù)器返回了200狀態(tài)并將靜態(tài)html傳回給客戶端。同時,服務(wù)器還帶上了ETag和Last-Modified兩個字段,我們先繼續(xù)往下看。此時客戶端做了幾件事情:

  • 緩存了靜態(tài)資源的內(nèi)容;
  • 記錄了該內(nèi)容的ETag和Last-Modified。

(4) 點擊瀏覽器刷新按鈕

點擊瀏覽器的刷新按鈕后,客戶端瀏覽器帶上了第一次請求時返回的ETag和Last-Modified再次請求了服務(wù)器。服務(wù)端通過這兩個參數(shù)認為客戶端已經(jīng)緩存了資源,服務(wù)器不需要再次返回資源了。于是服務(wù)器返回了304。

那如果有代理服務(wù)器摻和進來又是一個什么樣的場景呢?還記得我們之前配置的那臺代理服務(wù)器嗎,我們將代理服務(wù)的代理緩存時間設(shè)定在了10秒。

(5) 第一次訪問

(6) 點擊瀏覽器刷新按鈕

點擊瀏覽器的刷新按鈕時,客戶端瀏覽器帶上了第一次請求時返回的ETag和Last-Modified再次請求了服務(wù)器。服務(wù)端通過這兩個參數(shù)認為客戶端已經(jīng)緩存了資源,服務(wù)器不需要再次返回資源了,于是服務(wù)器返回了304。

注意這次刷新時,ngiux-cache-status的狀態(tài)時HIT標識這次命中了代理服務(wù)器的緩存,這次的客戶端緩存有效性判斷是由代理服務(wù)器完成的。

(7) 10秒后的第三次刷新

前面說了 代理服務(wù)器的緩存有效期,我們配置成了10秒。第三次刷新時服務(wù)器依然返回了304,資源不需要更新。

但是這次刷新時,ngiux-cache-status的狀態(tài)是EXPIRED,這標識代理服務(wù)器的緩存已經(jīng)失效了,不能用來做有效性判斷, 這個時候,代理服務(wù)器就會將這次的請求透傳給靜態(tài)資源服務(wù)器(源服務(wù)器),通過靜態(tài)資源服務(wù)器(源服務(wù)器)完成的緩存的有效性判斷。

在這個過程中,代理服務(wù)器又會對自己的緩存進行更新,于是有了下面第四次。

(8) 第四次刷新

邏輯圖如下:

通過這四次請求,我們能夠清晰的了解了整個的邏輯,代理服務(wù)器在某些情況下直接代替了靜態(tài)資源服務(wù)器(源服務(wù)器)。因為public指令告訴代理服務(wù)器,可以緩存數(shù)據(jù),于是代理服務(wù)器按照配置將數(shù)據(jù)緩存了10秒,超過10秒后就會重新將請求轉(zhuǎn)發(fā)給靜態(tài)資源服務(wù)器(源服務(wù)器),同時重新進行緩存。

這時候有的同學會問了,代理服務(wù)器有緩存的時間限制,在沒有達到時間限制之前是不會重新請求靜態(tài)資源服務(wù)器(源服務(wù)器)的,這時候就降低了靜態(tài)資源服務(wù)器(源服務(wù)器)的壓力。那為什么在上面的例子里面,瀏覽器一直在請求代理服務(wù)器呢?

這里要跟大家說明一下,在上述的案例中,我們其實一直在點擊瀏覽器的刷新按鈕,刷新按鈕的意思就是讓客戶端瀏覽器重新請求服務(wù)器來驗證緩存內(nèi)容的有效性。

大家仔細看下所有截圖中的Request-Header 是不是都有一個max-age = 0 ,這個指令就是瀏覽器在刷新請求時,告訴服務(wù)器——我本地的緩存可能到期了,你要幫我驗證一下。如果你嘗試將網(wǎng)址復制到瀏覽器的新窗口然后點擊回車打開url,而不是點擊刷新按鈕,這個時候就會像下圖這樣。

瀏覽器不會訪問網(wǎng)絡(luò),注意看Status Code 那里括號里面的備注,Status Code: 200 OK (from disk cache) 表示這次的響應(yīng)數(shù)據(jù),其實是從磁盤緩存里面拿的。

在android系統(tǒng)的WebView中,正常情況下是沒有提供刷新按鈕的(除非開發(fā)者自己寫一個)那么這種場景下webview就不會請求網(wǎng)絡(luò),每次都從磁盤緩存中拿數(shù)據(jù),對應(yīng)在抓包時,就看不到網(wǎng)絡(luò)請求。

了解了整個邏輯之后,我們再來看mozilla提供的描述,再結(jié)合上述的邏輯,是不是就已經(jīng)有了初步的概念了。

4.4.10 在響應(yīng)頭中的可緩存性控制

(1) public

表明響應(yīng)可以被任何對象(包括:發(fā)送請求的客戶端,代理服務(wù)器,等等)緩存,即使是通常不可緩存的內(nèi)容。例如:

  • 該響應(yīng)沒有max-age指令或Expires消息頭;
  • 該響應(yīng)對應(yīng)的請求方法是 POST 。

這個其實就是我們剛剛驗證的場景。

(2) private

表明響應(yīng)只能被單個用戶緩存,不能作為共享緩存(即代理服務(wù)器不能緩存它)。私有緩存可以緩存響應(yīng)內(nèi)容,比如:對應(yīng)用戶的本地瀏覽器。

如果使用private,代表著這個資源,可以被私有用戶緩存,緩存不會被共享,實際測試,當標注為private時,瀏覽器可以進行緩存,但是代理服務(wù)器不會緩存這個資源。有些材料里面提到,private是可以指定緩存的user_id的,這種屬于比較復雜的配置了,有興趣的同學可以研究下。

(3) no-cache

強制要求緩存把請求提交給原始服務(wù)器進行驗證(協(xié)商緩存驗證)。

這是一個服務(wù)端經(jīng)常使用的指令,也是一個比較容易與no-store混淆的指令,許多前端和客戶端的同學都認為當服務(wù)端的響應(yīng)中標注了no-cache,那么客戶端就不會進行緩存,每次都會請求服務(wù)器獲取新的內(nèi)容。其實只說對了一半。

在這種場景下,瀏覽器確實會每次都請求服務(wù)器,但是并不意味著瀏覽器不緩存資源,mozilla的官方解釋是“把請求提交給原始服務(wù)器進行驗證”如果緩存沒有問題,那么服務(wù)器就會返回304,讓瀏覽器繼續(xù)使用自己本地的緩存”。

(4) no-store

不應(yīng)存儲有關(guān)客戶端請求或服務(wù)器響應(yīng)的任何內(nèi)容,即不使用任何緩存。

這個指令就是完全不使用本地緩存,在這種模式下,客戶端不會記錄任何緩存,包括Etag等,每次都會重新發(fā)起請求,并且得到200響應(yīng)和對應(yīng)的數(shù)據(jù)。如果前端希望自己的網(wǎng)頁完全不被緩存,那么可以試下這個指令。

以上指令解決了客戶端以及代理服務(wù)器能不能緩存的問題,有的同學就會有疑問了,如果讓客戶端進行本地緩存,那么正常情況下如果不去手動刷新,客戶端是不會請求服務(wù)器的,前端發(fā)新版后,客戶端如何選擇合適的時機請求服務(wù)器呢?

這個時候就要用到緩存有效性控制。瀏覽器和服務(wù)器之間的緩存校驗是相互的 ,也就是說服務(wù)器可以告知瀏覽器 這個緩存你能用多久,能保留多久。

先來看下服務(wù)器是如何通知客戶端緩存可以用多久的。緩存有效性控制指令一般會與可緩存性指令共同下發(fā)給客戶端。

我們在server的header中增加max-age屬性,同時,為了避免代理服務(wù)器提前將代理緩存置為無效,我們將代理服務(wù)器的緩存有效時間設(shè)置到100秒,超過靜態(tài)資源服務(wù)器(源服務(wù)器)設(shè)置的max-age = 20。

第一次請求:

我們使用刷新功能刷新瀏覽器,在20秒內(nèi)我們持續(xù)得到HIT的狀態(tài),說明命中了代理服務(wù)器的緩存。20秒之后 代理服務(wù)器返回EXPIRED 說明代理服務(wù)器響應(yīng)了靜態(tài)資源服務(wù)器(源服務(wù)器)的指示,讓本地代理失效了,而代理服務(wù)器設(shè)置的100秒本地緩存時間,這個時候被忽略了。

這次我們依然使用了瀏覽器的刷新功能來強制瀏覽器去服務(wù)器校驗緩存的有效性,也就是說其實在上面的測試中,瀏覽器每次都是自己忽略max-age,去訪問服務(wù)器的。

結(jié)論:新增的max-age,控制了代理服務(wù)器保留的緩存時長,本地代理會忽略配置中的緩存時長直接使用靜態(tài)資源服務(wù)器(源服務(wù)器)下發(fā)的max-age作為緩存時長。

下面為了測試瀏覽器如何使用本地緩存,我們用android上的webview來進行實驗,因為webview是沒有刷新按鈕的(除非開發(fā)者自己造一個)。

第一次打開:

打開后在后面我們每隔兩秒再打開一次:

可以看到20秒內(nèi),webview都沒有重復請求服務(wù)器下載站點的index.html,在上面的截圖中,每顯示一個favicon.ico就是我打開一次站點鏈接,因為我沒有在源服務(wù)器中配置favicon.ico,所以每次打開,webview都在找服務(wù)器下載這個資源。

超過20秒后,webview發(fā)起了請求,此次服務(wù)器返回了304,要求客戶端繼續(xù)使用緩存進行展示,這次max-age指令體現(xiàn)出來了。而webview在這次校驗之后,會將本地的緩存再延長20秒的有效期,在下一個20秒后,webview才會再次發(fā)起新的緩存驗證請求。

總結(jié):客戶端webview會在public指令下緩存index.html,然后在max-age要求限制的時間內(nèi),都不會發(fā)起任何網(wǎng)絡(luò)請求來校驗資源。

在官網(wǎng)商城的一個案例中,網(wǎng)站上線后,運維沒有配置任何cache-control協(xié)議,在默認public的模式下,客戶端webview一直使用本地緩存,開發(fā)人員發(fā)現(xiàn)前端發(fā)版后,客戶端無法及時更新頁面。于是在每一個打開的網(wǎng)址后面手動拼接了一個時間戳,來強制改變網(wǎng)址,讓瀏覽器的緩存失效,其實只要使用nocache或者max-age作為cache-control協(xié)議就可以解決該問題。

除了max-age,cache-control在可緩存性控制指令的基礎(chǔ)上還可以增加如下幾個控制;

(1) no-transform

源服務(wù)端告訴客戶端,客戶端在緩存數(shù)據(jù)的時候不可以對文件進行改變,比如壓縮,格式修改等...

(2) must-revalidate

源服務(wù)端告知客戶端,一旦資源過期,在向靜態(tài)資源服務(wù)器(源服務(wù)器)發(fā)起驗證之前,該資源不得使用。

(3) proxy-revalidate

與must-revalidate作用相同,僅僅適用于共享緩存(例如代理)。

(4) max-age=

靜態(tài)資源服務(wù)器(源服務(wù)器)告知客戶端,X秒內(nèi),客戶端都不需要對緩存進行校驗,可以直接使用。

(5) s-maxage=

靜態(tài)資源服務(wù)器(源服務(wù)器)告知代理服務(wù)器,代理服務(wù)器可以在X秒內(nèi)使用該緩存,并且不需要進行校驗,直接可以使用,但是客戶端會忽略這個指令。

問題又來了,在驗證的過程中,服務(wù)器是怎么判斷瀏覽器的緩存是否有效的呢?

客戶端瀏覽器在有機會訪問服務(wù)器的時候就會告訴服務(wù)器,我的本地緩存是什么時候的數(shù)據(jù)(Last-Modified),數(shù)據(jù)內(nèi)容是什么(ETag),這樣服務(wù)端就能根據(jù)這兩個值來判斷客戶端的緩存是否是有效的。

我們來模擬一次前端的發(fā)版操作,將index.html的內(nèi)容進行修改;然后使用android webview進行請求。

這一次服務(wù)器毫不吝嗇的返回了200和數(shù)據(jù)。大家仔細觀察請求頭和響應(yīng)頭;

請求頭中的if-None-Match 其實就是保持的上次服務(wù)器返回的ETag;

請求頭中的if-Modified-Match 其實就是保持的上次服務(wù)器返回的Last-Modified;

現(xiàn)在這兩個值跟服務(wù)端的都對應(yīng)不上了,所以服務(wù)器返回了最新的數(shù)據(jù)和200狀態(tài)碼,并且?guī)狭俗钚碌腅tag,Last-Modified。而客戶端下一次請求時,就會帶上最新的Etag和Last-Modified。

在某些情況下,服務(wù)器返回的校驗字段會不完整,比如缺失了Etag和Last-Modified中某一個,那么這種情況下的緩存校驗就會存在風險。

在PC官網(wǎng)的一個案例中,源站點服務(wù)器返回了靜態(tài)資源的Etag和Last-Modified,但是代理服務(wù)器,也就是CDN廠商在返回時將Etag給清除了,導致缺少了Etag校驗。在正常情況下,服務(wù)器只使用文件的最后一次修改時間來做緩存校驗也沒啥問題。但是有這么一個用戶,他的瀏覽器內(nèi)緩存的靜態(tài)資源損壞了,瀏覽器每次讀取出來的資源無法使用,也就無法正常渲染頁面,但是在每次與服務(wù)器校驗資源的時候,服務(wù)器依然會告知客戶端304(緩存可用)。這種場景下,只要源站點服務(wù)器不進行資源更新,也就是不變動這個Last-Modified,那么用戶將永遠打不開這個文件。

講完了這些,差不多整個緩存協(xié)議的下行及交互部分大家已經(jīng)略知一二了。剩下的就是緩存協(xié)議的上行部分了,所謂上行部分就是將cache-control寫在瀏覽器訪問的請求頭上面。

前面我們也提過,瀏覽器的刷新請求,其實就是在請求頭里面加了一個cache-control :max-age = 0 。這其實是告知服務(wù)器,客戶端希望接收一個存在時間不大于0秒的緩存,一般的源服務(wù)器,特別是靜態(tài)資源服務(wù)器,這個時候就會根據(jù)客戶端的緩存情況返回200或者304。

4.4.11 在請求頭中的可緩存性控制

(1) no-cache

告知代理服務(wù)器,不直接使用緩存,要求向源服務(wù)器發(fā)起請求。

(2) no-store

所有的文件都不緩存到本地或者臨時文件夾中。

(3) max-age

告知服務(wù)器客戶端希望接收一個存在時間不大于X秒的資源。

(4) max-statle

告知服務(wù)器客戶端愿意接受一個超過緩存時間的資源,時間為X秒。

(5) min-fresh

告知服務(wù)器客戶端希望接收一個在小于X秒內(nèi)被更新過得資源。

(6) no-transform

告知代理服務(wù)器,不允許代理服務(wù)器對資源進行壓縮,轉(zhuǎn)化,比如有些代理服務(wù)器會對圖片進行壓縮,格式轉(zhuǎn)換。

(7) only-if-cached

告知代理服務(wù)器如果代理服務(wù)器有緩存內(nèi)容,就直接給,不用再找源服務(wù)器要。

請求頭中的緩存控制因為用的比較少,我就不過多的去解讀了,有興趣的同學可以去研究下。

五、總結(jié)

HTTP的cache-control協(xié)議規(guī)定了客戶端,代理服務(wù)器,源服務(wù)器三者之間的緩存交互邏輯。做為客戶端開發(fā),經(jīng)常出現(xiàn)一些與cache相關(guān)的問題在排查時無從下手,通過學習了解這部分內(nèi)容,可以幫助快速的分析定位這部分問題。

前端同學熟悉cache-control的邏輯后,也可以根據(jù)業(yè)務(wù)的形態(tài)跟運維討論自己緩存需求,有效的降低服務(wù)器的壓力和用戶的流量,提高網(wǎng)頁打開速度。

責任編輯:趙寧寧 來源: vivo互聯(lián)網(wǎng)技術(shù)
相關(guān)推薦

2017-09-21 10:00:07

緩存web服務(wù)器

2018-11-30 09:03:55

HTTP緩存Web

2015-10-27 13:37:14

瀏覽器HTTP緩存

2014-10-22 09:36:41

TCPIP

2017-05-19 08:05:08

瀏覽器緩存HTTP

2017-05-26 10:35:13

前端HTTP

2022-05-10 08:58:56

CacheHTTP

2018-07-12 15:30:03

HTTP緩存機制

2020-06-17 21:39:11

HTTP協(xié)議服務(wù)器

2019-08-23 06:36:32

2018-04-17 16:29:24

Java面試HTTP

2015-10-09 15:07:02

HTTP網(wǎng)絡(luò)協(xié)議

2021-10-18 08:35:50

HTTPSHTTP協(xié)議

2014-06-05 10:21:29

HTTP

2010-06-08 10:56:56

HTTP協(xié)議功能

2024-11-15 11:11:48

2018-09-30 14:45:15

IPFSHTTP互聯(lián)網(wǎng)協(xié)議

2014-11-13 10:57:03

http協(xié)議

2013-07-09 14:36:24

2021-05-18 08:31:46

緩存HTTP服務(wù)器
點贊
收藏

51CTO技術(shù)棧公眾號