緩存 - 一個奇妙的想法

太慢了!

HTTP 你過來一下,有件事想和你商量商量!」 瀏覽器老大晃悠到了 HTTP 的手術室中說道。程序員

「怎麼有空過來,正忙着呢,快坐。」 說着,我放下手中的器具,抽出放在一旁的凳子。json

「不了不了,我就想了解了解狀況,門口還有還多 URL 等着你發送呢!」 瀏覽器老大嘆了口氣。瀏覽器

我一看門外,嚇了一跳,門口的 URL 都已經圍着個人手術室繞了一圈了。「什麼狀況?」 我問道。緩存

「這個頁面的 HTTP 請求有點多啊!」 瀏覽器又嘆了口氣,緩緩的說道:「你想一想有什麼辦法能快一點?」服務器

「這我也沒有辦法呀,我這隻有 6 我的,要不你加點?」優化

「不行啊,瀏覽器空間過小了,操做系統老大不肯意在派人過來了,算了,你先忙,我想一想辦法!」 瀏覽器老大一臉的無奈。操作系統

協商

手術室外的 URL 慢慢的減小,大概過了 500ms 我終於放下了手中的手術刀,長舒一口氣,發現了還在手術室內來回踱步的瀏覽器老大。代理

HTTP 你有沒有發現,有一些 URL 你送了好幾回!」 瀏覽器老大如有所思道。code

「我沒注意誒,不過印象中是有的。」 說完,我陷入了思考。cdn

「那你回憶回憶,他們帶回來的數據,同樣嗎?」 瀏覽器老大想到了關鍵點。

「我想一想哈!」 我陷入了回憶中,喃喃自語道:「有一個 URL 來了 3 次,確實有,結果的話,是同樣的!」

「真的?那其實都不必發啊,直接拿上一次的數據給我就行啦!」 莊嚴的瀏覽器忽然興奮的像個小孩子。

「是沒錯,可是...」 我剛想開口。

「沒有可是!先這麼試試,把以前的數據給存一存,磁盤內存空間你本身調配哈。」 一臉興奮的瀏覽器忽然打斷個人話,跳着就出去了。

「這個老大有點精神大條啊,不行啊,這怎麼行啊。」 我自言自語道:「不過想法是個好想法,就是怎麼存,哪些資源須要存的問題。首先針對於數據的請求,我應該不用緩存,也就是 Content-type 裏有關於 json 的那些請求。其次也不能把文件一直存着吧,要是變了咋辦呢!那就先給個固定時間吧!不錯,哈哈!我真是個天才!!」

屏幕外的憤怒

「我靠,這 Chrome,我每次發版都要很久纔有反應,Google 上說這個是固定緩存時間!都什麼嘛!還讓不讓程序員幹活了!」

「加個時間戳吧,全部問題迎刃而解!」

「哎,也太不智能了啊,這但是 Chrome 啊!」

瀏覽器老大聽到略帶憤怒的聲音 Cue 到了他,不由一哆嗦,趕緊來到了 HTTP 的手術室!

HTTP 你怎麼搞的,如今屏幕外都抱怨起來了,我都聽到你們準備用 FireFox 了!」 瀏覽器老大急的滿頭汗。

「還不是上次你說的把數據給存起來,我還優化了下,至少沒有把 json 數據給存下來,要否則...」 忽然間我想到了 FireFox 一臉得意的樣子,也急了起來。

「怎麼辦!要不我們不優化吧!」 瀏覽器老大說道。

「其實吧,這幾天下來,我也思考了下,文件的緩存不該該由咱們來決定,你想他們(屏幕外的開發者)在發佈的時候會先把文件發到服務器上,若是服務器能夠通知咱們更新的話,那就最好不過了!」

「說的有道理,可是有一點,服務器不可能通知到咱們啊,由於鏈接是單向的。」 忽然間興奮又失落,瀏覽器老大嘆了口氣:「看來仍是不行啊!」

「不不不!這件事我要和我在服務器的哥們談談,老大你先別沮喪,我有個挺好的辦法的,我先驗證驗證。若是驗證經過了,那麼我有信心作好!」

「哦...」 瀏覽器老大還在失望的情緒裏,看來對個人想法不是很相信。

強緩存

拿起辦公桌上的電話,轉動幾圈後,聽筒裏傳來了 「嘟嘟」 聲。

「喂,你個不識相的,被派到 Chrome 就了不得了?這麼久纔來一個電話!」

「太忙了啊!說正事,我有個想法想和你談談!」

「什麼想法?我這也很忙啊,別說有點沒的啊,老孃忙着呢!」

「這個想法一擔實現,咱們的工做量會減輕很多呢!」 我頓了頓接着說道:「你有沒有發覺,其實有不少請求都是同樣的?」

「是啊,並且有時候還挺多的!說到這,我也想問,大家客戶端的 HTTP 怎麼總是請求同樣的東西?一直請求一直爽?」

「這個沒的辦法啊,用戶總是刷新頁面,還有有的用戶天天訪問的就那幾個頁面,這就致使了咱們常常向你要同一些東西。」

「那大家緩存下來啊!別動不動就向我要!」

「咱們已經開始試驗了,但實驗效果一直不理想,一開始咱們設定的緩存時間是一天,可是頁面的變更咱們徹底不知道!」

「是哦,這些天從你哪兒的請求確實少了很多。」

「如今瀏覽器老大由於緩存不更新數據這個問題,已經打算放棄緩存了!但我有個想法,能夠解決這個問題,須要試一試才行!」

「什麼想法,說吧,我來配合你!」

「還記得報文頭嗎?」

「固然,咱們不就幹這個的嗎?」

「你能夠給個資源的有效時間嗎?」

「有效時間?什麼意思?」

「就是資源不會發生變更的時長。」

「這個我也不知道咯!」

「讓開發者設置啊,把這個權限給他們,咱們約定這個有效時間放在報文頭中行吧!」

「嗯,是個不錯的想法,而後大家就根據這個設置,緩存對應的資源?」

bingo ~」

OK 那我向我這邊的應用層程序開放這個設置,報文頭中我給你加個 Expires 的字段,表明過時時間,你直接用就好!」

「這麼貼心!謝啦!」

「好嘞!那我先去通知一下!」

屏幕外的自責

「兄弟,很差意思哈,我剛剛把這個資源設置成了明天過時 ~~ 你強刷一下試試?」

「...」 默默的按下了 CTRL + F5 「兄弟,沒用...」

「啊!這個資源中間要走代理服務器...」

「那咋辦?」

「加個時間戳?」

「不行啊!」

「會不會你沒發成功?」

「...」

協商緩存

「喂?在嗎?」

「又有什麼事?老孃很忙的!」

「還記得上次我找你嗎?咱們加了個 Expires 的響應頭?」

「嗯,怎麼了,不挺好的嗎?大家把鍋成功摔給了咱們!」 電話那頭傳來了憤怒的聲音:「老孃真是着了你的道!這些開發者,明明本身設置了 Expires,還覺得沒發好,成天的往服務器上傳東西,煩死了!」

「消消氣 ~ 消消氣 ~ 我這還有一個事呢。」 我一臉尷尬的說道:「在改版以後呢,少了很多請求,可是咱們發現資源一旦過時了,咱們仍是得向大家要,但返回的數據咱們對比了下,仍是同樣的!因此這裏仍是須要和大家配合優化一下。」

「還來!」 電話那頭傳來了略帶憤怒的聲音:「還想甩鍋?」

「消消氣消消氣,想一想這能減小好多工做量呢!此次也是加一個響應頭就好 ~」

「說吧!」

「大家那邊能根據資源生成一個惟一標識嗎?就是資源變了這個標識也會變的那種。」

「能啊,這還不簡單,根據修改時間就行了啊!」

「原來這麼簡單啊,確實修改時間符合這個條件,那你把這個時間給咱們,咱們存下來,而後請求相同資源的時候咱們會把這個標識給大家,大家對比一下,若是同樣就直接返回 304 咱們就直接使用緩存了,行吧?是否是少了好多工做量?」

「確實!這個想法不錯!能減很多的工做量。行吧,給大家加上!就叫 Last-Modified 吧,大家的請求頭裏的就叫 If-Modified-Since 吧,我去通知應用層程序!」

「得嘞 ~」

翻新

「喂!在嗎?」

「喲,大忙人開始閒了?」 對面傳來了略帶嫉妒的聲音。

「對啊,自從開始使用咱們上次約定好的報文頭,工做量巨減啊,HTTP 協議升級了,據說了嗎?」 我有點小得意。

「是啊,升 1.1 了,終於可以長連了,可是效果不是很理想啊,該堵住的地方仍是堵住了。」 聽起來服務器那邊碰到了點難事。

「無論這個,還記得 Expires 這個首部嗎?」

「記得,就是過時時間嘛。」

「如今這個描述不許確,咱們本地時間和你給的不太一致,咱們客戶端想要的實際上是一個緩存的策略,好比緩存多久時間啊,如何緩存之類的,趁着協議升級,咱們也改改吧。」

「嗯,不錯,每次都要從新計算過時時間也是挺麻煩的,那這個就交給大家了,我這邊直接設置緩存策略。就叫 Cache-Control 吧!根據大家的使用狀況,來定規則,這個就交給你了。」

「嗯,好的。咱們這邊總結一下,等下傳真給你。」

「關於緩存,還有一個事,我也要提一下。」 電話那頭,語氣略帶抱歉。

「嗯嗯,你說。」

「其實根據修改時間來肯定緩存資源不是很準確,咱們這的規則是隻要文件被打開了就認爲是修改了,因此有偏差,還有就是若是文件的修改時間小於 1 秒,那個這個值實際上是不變的!」

「還有這樣的問題啊,那有解決辦法嗎?」

「咱們這能夠根據文章內容生成標識符,我經過新的報文頭 ETag 給大家,咱們這已經準備支持了。此次準備提到新的協議規範裏。」

OK 這不錯,那咱們使用哪一個字段給大家?」

If-None-Match

「好的,我記一下。」

URL 來了,我先掛了哈 ~ 策略等下給你傳真,你收一下!」

「嗯,忙去吧。」

Cache-Control

大約過了 100ms 服務端的傳真機開始打印,內容以下:

指令 做用
public 使用者均可以緩存(客戶端和代理服務器)。
private 僅客戶端能夠緩存(好比瀏覽器)。
max-age = time 僅緩存 time 所規定的時間,一旦緩存過時,須要從新請求。
s-max-age = time 僅在代理服務器中生效,覆蓋 max-age 效果。
no-store 不緩存響應。
no-cache 緩存,但緩存當即失效,配合 ETag 使用。
max-stable = time time 時間內,即便緩存失效,也使用緩存。
min-fresh = time 須要在 time 時間內,從新拿去資源。

失效不表明緩存清楚,僅僅表明緩存過時,若是服務器(也就是你)確認緩存有效,就使用緩存。

指令可組合使用,賦上組合使用結構圖:

Cache-Control 使用規則

該圖可做爲開發者文檔。

下圖爲咱們這邊總結的緩存命中規則,供大家參考:

命中緩存規則

相關閱讀

相關文章
相關標籤/搜索