對(duì)于開(kāi)發(fā)同學(xué)來(lái)說(shuō),CDN 這個(gè)詞,既熟悉又陌生。平搞開(kāi)發(fā)的時(shí)候很少需要碰這,但卻總能聽(tīng)到別人提起。們都聽(tīng)說(shuō)過(guò)它能加速,也大知道個(gè)原因,但是往深了問(wèn)用了 CDN 就一定比不用更快嗎?就感覺(jué)有些懵了。沒(méi)關(guān)系,今天我們換個(gè)角度新認(rèn)識(shí)下 CDN。CDN 是什么對(duì)于數(shù)字和文本類(lèi)型數(shù)據(jù),比方說(shuō)名字和電話(huà)號(hào)相關(guān)的信息。我們需要有個(gè)方存起來(lái)。我們通常會(huì)用 mysql 數(shù)據(jù)庫(kù)去存。文本存在 mysql 中當(dāng)我們需要重新將這一數(shù)據(jù)取出的候,就需要去讀 mysql 數(shù)據(jù)庫(kù)。但因?yàn)?mysql 的數(shù)據(jù)是存在磁盤(pán)上的,單臺(tái)實(shí)例,讀性能到差不多 5kqps 就已經(jīng)很不錯(cuò)了??雌饋?lái)還湊合,但對(duì)于稍大一點(diǎn)的系統(tǒng),就稍微有點(diǎn)急了。為了提升點(diǎn)性能,我在 mysql 之前再加一層內(nèi)存做緩存層,比如常崍山 redis,讀數(shù)據(jù)優(yōu)先到內(nèi)存里讀,讀不到才到 mysql 里讀,大大減少了讀 mysql 的次數(shù)。有了這套組合拳,讀性能輕松上 qps。mysql 和 redis好了,到這里,我們說(shuō)的都是我們平時(shí)敏山較容接觸的開(kāi)發(fā)場(chǎng)景。但如果現(xiàn)我要處理的,不再是上面提的文本類(lèi)數(shù)據(jù),而是圖片數(shù)。比如,我有一張帥氣的照。就下面這張。每次刷某音到有人翻唱蔡健雅的《letting go》的時(shí)候,我都忍不住想發(fā)這張圖。并配 "還是忘不了"。那么問(wèn)題來(lái)了。這張圖片數(shù)據(jù)應(yīng)該存哪?,又該從哪里讀?我們過(guò)頭去看 mysql 和 redis 的場(chǎng)景,無(wú)非就是存儲(chǔ)層加緩存層。存儲(chǔ)層緩存層對(duì)于圖片這樣的文件象,存儲(chǔ)層不太可能再用 mysql,應(yīng)該改用專(zhuān)業(yè)的對(duì)象存儲(chǔ),比如亞吉量遜的 S3(Amazon Simple Storage Service,注意后面是三個(gè) S 開(kāi)頭的單詞,所以叫 s3),或者阿里云的 oss(Object Storage Service)。下面的內(nèi)容,我們就用比較常的 oss 去做解釋。而緩存層,也不能繼續(xù)用 redis 了,需要改成使用 CDN(Content?Delivery?Network,內(nèi)容分發(fā)網(wǎng)絡(luò))??梢詫?CDN 簡(jiǎn)單理解為對(duì)象存儲(chǔ)對(duì)應(yīng)的緩存層。CDN 和 OSS現(xiàn)在就可以回答上面的提問(wèn),對(duì)用戶(hù)來(lái)說(shuō),這張片數(shù)據(jù)存在了對(duì)象存儲(chǔ)那,有需要的時(shí)候,會(huì)從 CDN 那被讀出來(lái)。CDN 的工作原理有了 CDN 和對(duì)象存儲(chǔ)之后,現(xiàn)在我們來(lái)看下們之間是怎么工作的。我們時(shí)看到的圖片,可以右鍵復(fù)查看它的 URL。1667103075060會(huì)發(fā)現(xiàn)圖片的 URL 長(zhǎng)這樣。https://cdn.xiaobaidebug.top/1667106197000.png其中前面的 cdn.xiaobaidebug.top 就是 CDN 的域名,后面的 1667106197000.png 是圖片的路徑名。當(dāng)我們?cè)?覽器輸入這個(gè) URL 就會(huì)發(fā)起 HTTP GET 請(qǐng)求,然后經(jīng)歷以下過(guò)程。CDN 的查詢(xún)流程第一階段: 你的電腦會(huì)先通過(guò) DNS 協(xié)議獲得 cdn.xiaobaidebug.top 這個(gè)域名對(duì)應(yīng)的 IP。?step1 和 step2:先查看瀏覽器緩存,再看操系統(tǒng)里的 / etc / hosts 緩存,如果都沒(méi)有,就會(huì)去詢(xún)問(wèn)最近的 DNS 服務(wù)器(比如你房間里的家用路由器諸犍。最近的 DNS 服務(wù)器上有沒(méi)有對(duì)應(yīng)的緩存,如果有則返女薎。?step3:如果最近的 DNS 服務(wù)器上沒(méi)有對(duì)應(yīng)的緩存,會(huì)去查詢(xún)根域,一級(jí)域,二域,三級(jí)域服務(wù)器。?step4:然后,最近的 DNS 服務(wù)器會(huì)得到這個(gè) cdn.xiaobaidebug.top 域名的別名(CNAME),比如 cdn.xiaobaidebug.top.w.kunlunaq.com。??kunlunaq.com 是阿里 CDN 專(zhuān)用的 DNS 調(diào)度系統(tǒng)。?step5 到 step7:此時(shí)最近的 DNS 服務(wù)器會(huì)去請(qǐng)求這個(gè) kunlunaq.com,然后返回一個(gè)離你最近的 IP 地址返回給你。第二階段: 對(duì)應(yīng)上圖里的 step8。瀏覽器拿著這個(gè) IP 去訪(fǎng)問(wèn) cdn 節(jié)點(diǎn),然后,cdn 節(jié)點(diǎn)返回?cái)?shù)據(jù)。上面第一階段流程里,提乘黃了很多的名詞,比如 CNAME,根域,一級(jí)域啥的,它們?cè)?前寫(xiě)的 「DNS 中有哪些值得學(xué)習(xí)的優(yōu)秀設(shè)計(jì)」有很細(xì)的描述,如果不了解的話(huà)以去看下。我們知道 DNS 的目的就是通過(guò)域名去獲得 IP 地址。但這只是它的眾多功能之一。DNS 消息有很多種類(lèi)型,其中 A 類(lèi)型,就是用域名去查域名對(duì)的 IP 地址。而 CNAME 類(lèi)型,則是用域名去查這個(gè)域名陽(yáng)山別名。對(duì)于普通名,DNS 解析后一般就能直接得到域名對(duì)應(yīng)巫戚 IP 地址(又叫 A 類(lèi)型記錄,A 指 Address)。比如下面,我用 dig 命令發(fā)出 DNS 請(qǐng)求并打印過(guò)程數(shù)據(jù)。$?dig?+trace?xiaobaidebug.top;;?ANSWER?SECTION:xiaobaidebug.top.?600?IN?A?47.102.221.141可以看到 xiaobaidebug.top 直接解析得到對(duì)應(yīng)的 IP 地址 47.102.221.141。但對(duì)于 cdn 域名,一波查詢(xún)下來(lái),先得到白狼是一條 CNAME 的記錄 xx.kunlunaq.com,然后 dig 這個(gè) xx.kunlunaq.com 才能得到對(duì)應(yīng)的 IP 地址。$?dig?+trace?cdn.xiaobaidebug.topcdn.xiaobaidebug.top.?600?IN?CNAME?cdn.xiaobaidebug.top.w.kunlunaq.com.$?dig?+trace?cdn.xiaobaidebug.top.w.kunlunaq.comcdn.xiaobaidebug.top.w.kunlunaq.com.?300?IN?A?122.228.7.243cdn.xiaobaidebug.top.w.kunlunaq.com.?300?IN?A?122.228.7.241cdn.xiaobaidebug.top.w.kunlunaq.com.?300?IN?A?122.228.7.244cdn.xiaobaidebug.top.w.kunlunaq.com.?300?IN?A?122.228.7.249cdn.xiaobaidebug.top.w.kunlunaq.com.?300?IN?A?122.228.7.248cdn.xiaobaidebug.top.w.kunlunaq.com.?300?IN?A?122.228.7.242cdn.xiaobaidebug.top.w.kunlunaq.com.?300?IN?A?122.228.7.250cdn.xiaobaidebug.top.w.kunlunaq.com.?300?IN?A?122.228.7.251看到這里,問(wèn)題就又來(lái)了。為什么要加個(gè) CNAME 那么麻煩?CNAME 里指向的,其實(shí)是 CDN 專(zhuān)用的 DNS 域名服務(wù)器,它對(duì)整個(gè) DNS 體系來(lái)說(shuō),只是其中一臺(tái)小小 DNS 域名服務(wù)器,看起來(lái)就跟其他域名象蛇務(wù)器一樣平平無(wú)奇。DNS 請(qǐng)求也會(huì)正常打入這個(gè)服務(wù)器里。魚(yú)婦請(qǐng)求真正打到它上面的時(shí)候它的特別之處就體現(xiàn)出來(lái)了當(dāng)查詢(xún)請(qǐng)求打入域名服務(wù)器,普通的 DNS 域名服務(wù)器返回域名對(duì)應(yīng)的部分 IP 就夠了,但 CDN 專(zhuān)用的 DNS 域名服務(wù)器卻會(huì)要求返回離調(diào)用方 " 最近的 " 服務(wù)器 IP。CDN 專(zhuān)用的 DNS 解析服務(wù)器會(huì)返回就近的 CDN 節(jié)點(diǎn) IP怎么知道哪個(gè)服務(wù)器 IP 里調(diào)用方最近?可以看到 "最近" 這個(gè)詞其實(shí)是加了雙引號(hào)的。CDN 專(zhuān)用的 DNS 域名服務(wù)器其實(shí)是 CDN 提供商提供的,比如阿里云當(dāng)然青蛇道自的的 CDN 節(jié)點(diǎn)有哪些,以及這些 CDN 服務(wù)器目前的負(fù)載情況和響應(yīng)延時(shí)甚權(quán)重啥的,并且也能知道調(diào)方的 IP 地址是什么,可以通過(guò)調(diào)用方的 IP 知道它所屬的運(yùn)營(yíng)商以及大概所地,根據(jù)條件篩選出最合適 CDN 服務(wù)器,這就是所謂的 " 最近 "。舉個(gè)例子。假設(shè)地理位置最近的 CDN 機(jī)房流量較多,響應(yīng)較慢,但地霍山位置遠(yuǎn)一些的服器卻能更好的響應(yīng)當(dāng)前請(qǐng)求那按理說(shuō)可能會(huì)選擇地理位遠(yuǎn)一些的那臺(tái) CDN 服務(wù)器。也就是說(shuō),選出來(lái)的服器不一定在地理位置最近,一定是當(dāng)前最合適的服務(wù)器回源是什么上面的圖片 URL,是 https://cdn 域名 / 圖片地址.png 的形式。也就是說(shuō)這張圖片是訪(fǎng)問(wèn) CDN 拿到的。那么,直接訪(fǎng)問(wèn)對(duì)象存能不能拿到圖片數(shù)據(jù)并展示比如像下面這樣。https://oss域名/圖片地址png這就像問(wèn),不走 redis,直接從 mysql 中能不能讀取到文本數(shù)據(jù)并展示一樣。當(dāng)然能。我之黃鷔在博客里的圖片就是這么干。但這樣成本更高,這里的本,可以指性能成本,也可指調(diào)用成本??聪孪旅孢@個(gè)。1667101182393可以看到直接請(qǐng)求 oss 的費(fèi)用差不多是通過(guò) cdn 請(qǐng)求 oss 的兩倍,考慮到家境貧寒,同時(shí)也為讓博客獲取圖片的速度更快我就接入了 CDN。但看到這里,問(wèn)題又又來(lái)了朱厭上面截圖里,紅框里有個(gè)詞叫 " 回源 "?;卦词鞘裁矗慨?dāng)我們?cè)L問(wèn) https://cdn 域名 / 圖片地址.png 時(shí),請(qǐng)求會(huì)打到 cdn 服務(wù)器上面。但 cdn 服務(wù)器本質(zhì)上就是一層緩存,并不麈數(shù)據(jù)源,對(duì)象儲(chǔ)才是數(shù)據(jù)源。第一次訪(fǎng)問(wèn) cdn 獲取某張圖片時(shí),大概率在 cdn 里并沒(méi)有這張圖片的數(shù)據(jù),因此需要升山數(shù)據(jù)源那去取出這份圖片數(shù)。然后再放到 cdn 上。下次再次訪(fǎng)問(wèn) cdn 時(shí),只要緩存不過(guò)期,就能命中存直接返回,這就不需要再源。于是訪(fǎng)問(wèn)的過(guò)程就變成下面這樣。1668605964836那還有哪些情況會(huì)發(fā)生回源呢?除了上面提到 cdn 上拿不到數(shù)據(jù)會(huì)回源站外,還有 cdn 上的緩存過(guò)期失效了也會(huì)導(dǎo)致回站。另外,就算有緩存,且存不過(guò)期,也可以通過(guò) cdn 提供的開(kāi)放接口來(lái)觸發(fā)主動(dòng)回源,但這個(gè)我們比較少會(huì)能接觸到。另外,回源這事情,其實(shí)用戶(hù)是感知不到,因?yàn)橛脩?hù)去讀圖片的時(shí)候只能知道自己讀到了還是讀到。同樣是讀到了,還細(xì)分是從 cdn 那直接讀的,還是 cdn 回源讀對(duì)象存儲(chǔ)之后返回的。倫山緩存直接回和沒(méi)緩存回源的區(qū)別那么我們有辦法判斷是否發(fā)生過(guò)源嗎?有。我們接著往下看怎么判斷是否發(fā)生回源我們某里云的對(duì)象存儲(chǔ)和 CDN 為例。假設(shè)我要請(qǐng)求下面這張圖 https://cdn.xiaobaidebug.top/ image / image-20220404094549469.png為了更方便的查看響應(yīng)數(shù)據(jù)的 http header,我們可以用上 postman。通過(guò) GET 方法去請(qǐng)求圖片數(shù)據(jù)。然后通下面的 tab 切換查看 response header 信息。查看 response header回源的情況此時(shí)查看 response header 下的 X-Cache 的值是?MISS TCP_MISS。意思是未命中緩存導(dǎo)致 CDN 回源查 oss,拿到數(shù)據(jù)后再返回。那此時(shí) CDN 里肯定是有這張圖片的緩存了。我們可西岳試著再執(zhí)行次 GET 方法獲取圖片。1667095186020X-Cache 的值就變成了?HIT TCP_MEM_HIT,這就是命中緩存了。這個(gè)是某里云的做法,其比如騰某云啥的,也都大差差,幾乎都可以從 response header 里找到相關(guān)的信息。用了 CDN 一定比不用的更快嗎?看到這里我們就可以回答魏書(shū)章頭的問(wèn)題了。如果沒(méi)有接入 CDN,直接訪(fǎng)問(wèn)源站,流程是這樣的。更新直接訪(fǎng)問(wèn)源但如果接入了 CDN,且 CDN 上沒(méi)有緩存數(shù)據(jù),那就會(huì)觸發(fā)回源巫即更新走了 CDN 還回源相當(dāng)于在原來(lái)的流程上還多了一層 CDN 的調(diào)用流程。也就是,用了 CDN 時(shí),未命中 CDN 緩存導(dǎo)致回源,就會(huì)比不用的時(shí)候更慢。未命中緩存,能是 cdn 里壓根就沒(méi)這一數(shù)據(jù),也可能是曾經(jīng)有這數(shù)據(jù)但后來(lái)過(guò)期失效了。這種情況都正常,大部分時(shí)候不需要做任何處理。但對(duì)于個(gè)別場(chǎng)景,我們可能需要做優(yōu)化。比如你們?cè)凑緮?shù)據(jù)有版本更新,就像更換 cdn 域名啥的,那在上線(xiàn)的那一刻用戶(hù)全用新 cdn 域名去請(qǐng)求圖片啥的,新 CDN 節(jié)點(diǎn)基本上百分百觸發(fā)回源,嚴(yán)重的時(shí)候甚至可能會(huì)鸮對(duì)象存儲(chǔ)。這時(shí)候你可能需提前將熱點(diǎn)數(shù)據(jù)篩選出來(lái),用工具預(yù)先請(qǐng)求一波,讓 CDN 加載上熱數(shù)據(jù)緩存。比如某里云上的 CDN 就有這樣的 " 刷新預(yù)熱 " 功能。cdn 刷新預(yù)熱當(dāng)然也可以通過(guò)灰度發(fā)布的模鴸鳥(niǎo)先讓少量用戶(hù)體驗(yàn)新功能,這些用戶(hù)把 cdn"熱" 起來(lái),然后再逐步放開(kāi)流量還有就是曾經(jīng)有這條數(shù)據(jù)但來(lái)過(guò)期失效了,對(duì)于熱點(diǎn)數(shù),可以適當(dāng)提高一下 cdn 數(shù)據(jù)的緩存時(shí)間。1667344813600什么情況下不應(yīng)該使用 CDN?從上面的描述看下來(lái),CDN 最大的優(yōu)勢(shì)在于,對(duì)于來(lái)自世各地的用戶(hù),它可以就近分 CDN 節(jié)點(diǎn)獲取數(shù)據(jù),并且多次重復(fù)獲取同一個(gè)文水馬據(jù)的時(shí)候,有緩存加速的作。這對(duì)于網(wǎng)頁(yè)圖片這樣的場(chǎng),是再合適不過(guò)了。因?yàn)榈?用的是對(duì)象存儲(chǔ),也就是說(shuō)只要是文件對(duì)象,比如視頻的,都可以用這套流程接入 cdn 做加速。比如平時(shí)刷的某音某手短視頻就是這么的。那反過(guò)來(lái)想想,問(wèn)題就了。什么情況下不應(yīng)該使用 CDN?如果你有一個(gè)公司內(nèi)網(wǎng)的服務(wù),并且服務(wù)請(qǐng)求獜片等文件不太可能被多次重調(diào)用,這時(shí)候其實(shí)沒(méi)必要使 CDN。注意上面兩個(gè)加粗了的關(guān)鍵點(diǎn)。?堵山內(nèi)網(wǎng)服務(wù)是為了保證你是了解服務(wù)的求來(lái)源的,也能拿到對(duì)象存的讀權(quán)限,并且如果你的對(duì)存儲(chǔ)也是公司內(nèi)部的,那大率跟你的服務(wù)已經(jīng)在同一個(gè)房里,這已經(jīng)很近了。接入 CDN 也享受不到 "就近分配 CDN 節(jié)點(diǎn)" 所帶來(lái)的好處。??圖片或其他件不太可能被多次重復(fù)使用如果接入了 CDN,那你每次去訪(fǎng)問(wèn) CDN 獲取圖片的時(shí)候,CDN 節(jié)點(diǎn)上大概率沒(méi)有你要的數(shù)據(jù),尚鳥(niǎo)當(dāng)于次都需要回源到對(duì)象存儲(chǔ)去一把。那接入 CDN 相當(dāng)于給自己加了一層代理,多層代理,就多一層耗時(shí)。1668612494972關(guān)于上面的第二點(diǎn),如果你需要個(gè)明確的指標(biāo)去說(shuō)服自己,我可以給你一個(gè)。從上面的紹內(nèi)容,我們知道,可以通 cdn 響應(yīng)的 http header 中的 X-Cache 字段,看到一個(gè)請(qǐng)求是否觸發(fā)過(guò)回應(yīng)龍,統(tǒng)計(jì)數(shù),再除以總的請(qǐng)求數(shù),就得到回源的比例,比如回源例高達(dá) 90%,那還接啥 cdn??偨Y(jié)??對(duì)于文本類(lèi)數(shù)據(jù)我們習(xí)鮮山用 mysql 做存儲(chǔ),redis 做緩存。但屬于文件類(lèi)數(shù)據(jù),比視頻圖片,則需要使用 oss 等做對(duì)象存儲(chǔ),cdn 做緩存。??用了 CDN 如果發(fā)生回源,那實(shí)際上會(huì)不用的時(shí)候更慢一些。??CDN 最大的優(yōu)勢(shì)在于,對(duì)于來(lái)自世界蜚地的用戶(hù),它可就近分配 CDN 節(jié)點(diǎn)獲取數(shù)據(jù),并且多次重復(fù)獲取同個(gè)文件數(shù)據(jù)的時(shí)候,有緩存速的作用。如果你的服務(wù)和象存儲(chǔ)都在內(nèi)網(wǎng),并且文件據(jù)也不太會(huì)有重復(fù)使用的可性,那其實(shí)沒(méi)必要接入 cdn。本文來(lái)自微信公眾號(hào):小白 debug (ID:xiaobaidebug),作者:小?