CDN 是什么,用了 CDN 就一定比不用更快吗
對于開發同學來說,CDN 這個詞,既熟悉又陌生。
平時搞開發的時候很少需要碰這個,但卻總能聽到別人提起。
我們都聽說過它能加速,也大概知道個原因,但是往深了問。
用了 CDN 就一定比不用更快嗎?
就感覺有些懵了。但沒關系,今天我們換個角度重新認識下 CDN。
CDN 是什么
對于數字和文本類型的數據,比方說名字和電話號碼相關的信息。我們需要有個地方存起來。
我們通常會用 mysql 數據庫去存。
當我們需要重新將這一數據取出的時候,就需要去讀 mysql 數據庫。
但因為 mysql 的數據是存在磁盤上的,單臺實例,讀性能到差不多 5kqps 就已經很不錯了。
看起來還湊合,但對于稍微大一點的系統,就稍微有點捉急了。
為了提升點性能,我們在 mysql 之前再加一層內存做緩存層,比如常說的 redis,讀數據優先到內存里讀,讀不到才到 mysql 里讀,大大減少了讀 mysql 的次數。有了這套組合拳,讀性能輕松上萬 qps。
好了,到這里,我們說的都是我們平時比較容易接觸的開發場景。
但如果現在我要處理的,不再是上面提到的文本類數據,而是圖片數據。
比如,我有一張帥氣的照片。就下面這張。
每次刷某音聽到有人翻唱蔡健雅的《letting go》的時候,我都忍不住想發這張圖。
并配文 "還是忘不了"。
那么問題來了。
這張圖片數據應該存在哪?,又該從哪里讀?
我們回過頭去看 mysql 和 redis 的場景,無非就是存儲層加緩存層。
對于圖片這樣的文件對象,存儲層不太可能再用 mysql,應該改用專業的對象存儲,比如亞馬遜的 S3(Amazon Simple Storage Service,注意后面是三個 S 開頭的單詞,所以叫 s3),或者阿里云的 oss(Object Storage Service)。下面的內容,我們就用比較常見的 oss 去做解釋。
而緩存層,也不能繼續用 redis 了,需要改成使用 CDN(ContentDeliveryNetwork,內容分發網絡)。
可以將 CDN 簡單理解為對象存儲對應的緩存層。
現在就可以回答上面的提問,對用戶來說,這張圖片數據存在了對象存儲那,當有需要的時候,會從 CDN 那被讀出來。
CDN 的工作原理
有了 CDN 和對象存儲之后,現在我們來看下他們之間是怎么工作的。
我們平時看到的圖片,可以右鍵復制查看它的 URL。
會發現圖片的 URL 長這樣。
https://cdn.xiaobaidebug.top/1667106197000.png
其中前面的 cdn.xiaobaidebug.top 就是 CDN 的域名,后面的 1667106197000.png 是圖片的路徑名。
當我們在瀏覽器輸入這個 URL 就會發起 HTTP GET 請求,然后經歷以下過程。
第一階段: 你的電腦會先通過 DNS 協議獲得 cdn.xiaobaidebug.top 這個域名對應的 IP。
?step1 和 step2:先查看瀏覽器緩存,再看操作系統里的 / etc / hosts 緩存,如果都沒有,就會去詢問最近的 DNS 服務器(比如你房間里的家用路由器)。最近的 DNS 服務器上有沒有對應的緩存,如果有則返回。
?step3:如果最近的 DNS 服務器上沒有對應的緩存,就會去查詢根域,一級域,二級域,三級域服務器。
?step4:然后,最近的 DNS 服務器會得到這個 cdn.xiaobaidebug.top 域名的別名(CNAME),比如 cdn.xiaobaidebug.top.w.kunlunaq.com。
?kunlunaq.com 是阿里 CDN 專用的 DNS 調度系統。
?step5 到 step7:此時最近的 DNS 服務器會去請求這個 kunlunaq.com,然后返回一個離你最近的 IP 地址返回給你。
第二階段: 對應上圖里的 step8。瀏覽器拿著這個 IP 去訪問 cdn 節點,然后,cdn 節點返回數據。
上面第一階段流程里,提到了很多新的名詞,比如 CNAME,根域,一級域啥的,它們在之前寫的 「DNS 中有哪些值得學習的優秀設計」有很詳細的描述,如果不了解的話可以去看下。
我們知道 DNS 的目的就是通過域名去獲得 IP 地址。
但這只是它的眾多功能之一。
DNS 消息有很多種類型,其中 A 類型,就是用域名去查域名對應的 IP 地址。而 CNAME 類型,則是用域名去查這個域名的別名。
對于普通域名,DNS 解析后一般就能直接得到域名對應的 IP 地址(又叫 A 類型記錄,A 指 Address)。
比如下面,我用 dig 命令發出 DNS 請求并打印過程數據。
$dig+tracexiaobaidebug.top ;;ANSWERSECTION: xiaobaidebug.top.600INA47.102.221.141
可以看到 xiaobaidebug.top 直接解析得到對應的 IP 地址 47.102.221.141。
但對于 cdn 域名,一波查詢下來,先得到的卻是一條 CNAME 的記錄 xx.kunlunaq.com,然后 dig 這個 xx.kunlunaq.com 才能得到對應的 IP 地址。
$dig+tracecdn.xiaobaidebug.top cdn.xiaobaidebug.top.600INCNAMEcdn.xiaobaidebug.top.w.kunlunaq.com. $dig+tracecdn.xiaobaidebug.top.w.kunlunaq.com cdn.xiaobaidebug.top.w.kunlunaq.com.300INA122.228.7.243 cdn.xiaobaidebug.top.w.kunlunaq.com.300INA122.228.7.241 cdn.xiaobaidebug.top.w.kunlunaq.com.300INA122.228.7.244 cdn.xiaobaidebug.top.w.kunlunaq.com.300INA122.228.7.249 cdn.xiaobaidebug.top.w.kunlunaq.com.300INA122.228.7.248 cdn.xiaobaidebug.top.w.kunlunaq.com.300INA122.228.7.242 cdn.xiaobaidebug.top.w.kunlunaq.com.300INA122.228.7.250 cdn.xiaobaidebug.top.w.kunlunaq.com.300INA122.228.7.251
看到這里,問題就又來了。
為什么要加個 CNAME 那么麻煩?
CNAME 里指向的,其實是 CDN 專用的 DNS 域名服務器,它對整個 DNS 體系來說,只是其中一臺小小的 DNS 域名服務器,看起來就跟其他域名服務器一樣,平平無奇。DNS 請求也會正常打入這個服務器里。
但當請求真正打到它上面的時候,它的特別之處就體現出來了,當查詢請求打入域名服務器時,普通的 DNS 域名服務器返回域名對應的部分 IP 就夠了,但 CDN 專用的 DNS 域名服務器卻會要求返回離調用方 " 最近的 " 服務器 IP。
怎么知道哪個服務器 IP 里調用方最近?
可以看到 "最近" 這個詞其實是加了雙引號的。
CDN 專用的 DNS 域名服務器其實是 CDN 提供商提供的,比如阿里云當然知道自己的的 CDN 節點有哪些,以及這些 CDN 服務器目前的負載情況和響應延時甚至權重啥的,并且也能知道調用方的 IP 地址是什么,可以通過調用方的 IP 知道它所屬的運營商以及大概所在地,根據條件篩選出最合適的 CDN 服務器,這就是所謂的 " 最近 "。
舉個例子。假設地理位置最近的 CDN 機房流量較多,響應較慢,但地理位置遠一些的服務器卻能更好的響應當前請求,那按理說可能會選擇地理位置遠一些的那臺 CDN 服務器。
也就是說,選出來的服務器不一定在地理位置最近,但一定是當前最合適的服務器。
回源是什么
上面的圖片 URL,是 https://cdn 域名 / 圖片地址.png 的形式。
也就是說這張圖片是訪問 CDN 拿到的。
那么,直接訪問對象存儲能不能拿到圖片數據并展示?
比如像下面這樣。
https://oss域名/圖片地址png
這就像問,不走 redis,直接從 mysql 中能不能讀取到文本數據并展示一樣。
當然能。
我之前放在博客里的圖片就是這么干的。
但這樣成本更高,這里的成本,可以指性能成本,也可以指調用成本。看下下面這個圖。
可以看到直接請求 oss 的費用差不多是通過 cdn 請求 oss 的兩倍,考慮到家境貧寒,同時也為了讓博客獲取圖片的速度更快,我就接入了 CDN。
但看到這里,問題又又來了。
上面的截圖里,紅框里有個詞叫 " 回源 "。
回源是什么?
當我們訪問 https://cdn 域名 / 圖片地址.png 時,請求會打到 cdn 服務器上面。
但 cdn 服務器本質上就是一層緩存,并不是數據源,對象存儲才是數據源。
第一次訪問 cdn 獲取某張圖片時,大概率在 cdn 里并沒有這張圖片的數據,因此需要回到數據源那去取出這份圖片數據。然后再放到 cdn 上。下次再次訪問 cdn 時,只要緩存不過期,就能命中緩存直接返回,這就不需要再回源。
于是訪問的過程就變成了下面這樣。
那還有哪些情況會發生回源呢?
除了上面提到的 cdn 上拿不到數據會回源站外,還有 cdn 上的緩存過期失效了也會導致回源站。
另外,就算有緩存,且緩存不過期,也可以通過 cdn 提供的開放接口來觸發主動回源,但這個我們比較少機會能接觸到。
另外,回源這個事情,其實用戶是感知不到的,因為用戶去讀圖片的時候,只能知道自己讀到了還是讀不到。
同樣是讀到了,還細分為是從 cdn 那直接讀的,還是 cdn 回源讀對象存儲之后返回的。
那么,我們有辦法判斷是否發生過回源嗎?
有。我們接著往下看。
怎么判斷是否發生回源
我們以某里云的對象存儲和 CDN 為例。
假設我要請求下面這張圖 https://cdn.xiaobaidebug.top/ image / image-20220404094549469.png
為了更方便的查看響應數據的 http header,我們可以用上 postman。
通過 GET 方法去請求圖片數據。
然后通過下面的 tab 切換查看 response header 信息。
此時查看 response header 下的 X-Cache 的值是MISS TCP_MISS。意思是未命中緩存導致 CDN 回源查 oss,拿到數據后再返回。
那此時 CDN 里肯定是有這張圖片的緩存了。我們可以試著再執行一次 GET 方法獲取圖片。
X-Cache 的值就變成了HIT TCP_MEM_HIT,這就是命中緩存了。
這個是某里云的做法,其他比如騰某云啥的,也都大差不差,幾乎都可以從 response header 里找到相關的信息。
用了 CDN 一定比不用的更快嗎?
看到這里我們就可以回答文章開頭的問題了。
如果沒有接入 CDN,直接訪問源站,流程是這樣的。
但如果接入了 CDN,且 CDN 上沒有緩存數據,那就會觸發回源。
相當于在原來的流程上還多了一層 CDN 的調用流程。
也就是,用了 CDN 時,未命中 CDN 緩存導致回源,就會比不用的時候更慢。
未命中緩存,可能是 cdn 里壓根就沒這一數據,也可能是曾經有這條數據但后來過期失效了。
這兩種情況都正常,大部分時候并不需要做任何處理。
但對于極個別場景,我們可能需要做些優化。比如你們源站數據有大版本更新,就像更換 cdn 域名啥的,那在上線的那一刻用戶全用新 cdn 域名去請求圖片啥的,新 CDN 節點基本上百分百觸發回源,嚴重的時候甚至可能會拖垮對象存儲。這時候你可能需要提前將熱點數據篩選出來,利用工具預先請求一波,讓 CDN 加載上熱數據緩存。比如某里云上的 CDN 就有這樣的 " 刷新預熱 " 功能。
當然也可以通過灰度發布的模式,先讓少量用戶體驗新功能,讓這些用戶把 cdn"熱" 起來,然后再逐步放開流量。
還有就是曾經有這條數據但后來過期失效了,對于熱點數據,可以適當提高一下 cdn 數據的緩存時間。
什么情況下不應該使用 CDN?
從上面的描述看下來,CDN 最大的優勢在于,對于來自世界各地的用戶,它可以就近分配 CDN 節點獲取數據,并且多次重復獲取同一個文件數據的時候,有緩存加速的作用。
這對于網頁圖片這樣的場景,是再合適不過了。因為底層用的是對象存儲,也就是說,只要是文件對象,比如視頻啥的,都可以用這套流程接入 cdn 做加速。比如平時刷的某音某手短視頻就是這么干的。
那反過來想想,問題就來了。
什么情況下不應該使用 CDN?
如果你有一個公司內網的服務,并且服務請求的圖片等文件不太可能被多次重復調用,這時候其實沒必要使用 CDN。
注意上面兩個加粗了的關鍵點。
?內網服務,是為了保證你是了解服務的請求來源的,也能拿到對象存儲的讀權限,并且如果你的對象存儲也是公司內部的,那大概率跟你的服務已經在同一個機房里,這已經很近了。接入 CDN 也享受不到 "就近分配 CDN 節點" 所帶來的好處。
?圖片或其他文件不太可能被多次重復使用,如果接入了 CDN,那你每次去訪問 CDN 獲取圖片的時候,CDN 節點上大概率沒有你要的數據,相當于每次都需要回源到對象存儲去取一把。那接入 CDN 相當于給自己加了一層代理,多一層代理,就多一層耗時。
關于上面的第二點,如果你需要一個明確的指標去說服自己,那我可以給你一個。從上面的介紹內容,我們知道,可以通過 cdn 響應的 http header 中的 X-Cache 字段,看到一個請求是否觸發過回源,統計次數,再除以總的請求數,就能得到回源的比例,比如回源比例高達 90%,那還接啥 cdn。
總結
?對于文本類數據我們習慣用 mysql 做存儲,redis 做緩存。但屬于文件類數據,比如視頻圖片,則需要使用 oss 等做對象存儲,cdn 做緩存。
?用了 CDN 如果發生回源,那實際上會比不用的時候更慢一些。
?CDN 最大的優勢在于,對于來自世界各地的用戶,它可以就近分配 CDN 節點獲取數據,并且多次重復獲取同一個文件數據的時候,有緩存加速的作用。如果你的服務和對象存儲都在內網,并且文件數據也不太會有重復使用的可能性,那其實沒必要接入 cdn。
本文來自微信公眾號:小白 debug (ID:xiaobaidebug),作者:小白
總結
以上是生活随笔為你收集整理的CDN 是什么,用了 CDN 就一定比不用更快吗的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2299 元起,vivo S18 / P
- 下一篇: 极氪汽车发布首款自研“金砖”电池:极氪