CDN 為什麼這麼設計?

2022.06.14
CDN 為什麼這麼設計?

CDN 網絡的建設成本還是很大的,只有大公司會自建,一般我們都會買三方服務,而且國內和海外的CDN 都是分開的,如果主要服務國內用戶,那隻買國內的CDN 服務即可。有了這套覆蓋全國、全球的CDN 節點網絡之後,我們才能更快地打開網站。

過去幾十年,計算機網絡把幾乎全世界的計算機都連接了起來,我們只要把靜態資源和動態的代碼部署到服務器上,然後啟動服務監聽某個端口,這樣世界各地的計算機就都能訪問該網站。

但是這樣有個問題,資源最終還是通過物理層網絡線路和設備傳輸的,每經過一段線路、一個網絡設備都有一些耗時,所以客戶端和服務器相距越遠,網站打開速度就越慢。

這就像你從海南買了一件東西,如果你人在廣州的話,那可能很快就收到了,因為傳輸距離近,但如果你在北京的話,那可能就要多等幾天了,因為中間經過的線路、節點都比較多。

但這樣肯定不行的,用戶體驗會很差。怎麼解決這個問題呢?

離得越遠網站打開速度就越慢,很容易想到,如果部署到很多個地方,當用戶訪問網絡的時候,訪問最近的那個不就行了?

這就像快遞都有一些中轉的倉庫,可以存放一些貨物,如果你人在北京,要買一個海南的東西,恰好北京的倉庫裡有,那豈不是很快就可以收到了。

思路是沒問題,但是怎麼實現呢?

用戶是通過域名訪問網站的,那能不能通過DNS 服務器來實現這個功能呢?

前面寫過一篇 ​​DNS 原理的文章​​,這裡簡單回顧下:

圖片

客戶端訪問某個域名的時候,會先查找本地hosts 文件,如果能查到ip 就直接訪問。

否則會向本地DNS 服務器發請求,這個是聯通、移動等運營商提供的每個城市都有的DNS 服務器。由它去域名服務器發送解析域名的請求,然後把結果返給客戶端。

域名是分層解析的,有根域名服務器、頂級域名服務器、權威域名服務器三層,比如image.baidu.com 會先向根域名服務器發請求查詢com 的頂級域名服務器的ip,然後再向com 頂級域名服務器查詢image.baidu.com 的權威域名服務器的ip。查詢到權威域名服務器之後,任意層級的域名都會在這裡解析(所以叫權威域名服務器)。

看到這個權威域名服務器的時候,不知道大家是否就想到怎麼實現CDN 網絡了。

能不能在權威域名服務器這一層根據客戶端的ip 做一下負載均衡呢?比如北京來的DNS 請求就返回北京機房的服務器的ip,上海來的DNS 請求就返回上海機房的服務器的ip。

確實可以這樣實現內容的就近分發,這樣的負載均衡網絡就叫做CDN (Conent Delivery Network)

但是實現這樣一個CDN 網絡需要在全國建立多個機房,成本太高了,所以只有像百度、阿里、騰訊這類大公司才會自建CDN,一般情況下我們都會買第三方的CDN 服務來用。

這些公司建好了CDN 網絡,實際上自己也是用不完的,也會對外提供CDN 加速服務。

第三方的CDN 服務自然也要提供一個DNS 服務器,也就是實現根據ip 返回不同城市的服務器的ip 的那個。

比如這是百度雲CDN 的原理圖:

圖片

用戶向本地DNS 服務器發請求之後,經歷根域名、頂級域名的DNS 解析,最終會轉給權威DNS 服務器。這時候只要權威DNS 服務器再轉給baidu 的DNS 服務器就可以了,這樣就能接入CDN 服務。

baidu 的DNS 服務器實現了負載均衡,會根據請求ip 所在的城市,返回不同城市的服務器的ip。也就實現了就近分發的網絡加速功能。

那這個從權威DNS 到baidu 的DNS 的轉發是怎麼實現的呢?

DNS 的記錄有很多種類型,比如:

A 代表address,記錄域名對應的ip。

CNAME 代表域名還有一個別名,可以向那個域名來查ip。

MX 代表件名後綴對應的域名或者IP

看到這個CNAME 類型,大家應該就想到怎麼實現轉發了。

只要自己在DNS服務器上配一條CNAME 的記錄,指向CDN 服務器的域名就可以了。

比如你用某雲的CDN 的時候,第一步也是要配置下自己的DNS 服務器的CNAME 指向它:

圖片

這樣,當你訪問某個域名的時候,解析域名的權威服務器會返回CDN 服務的DNS 服務器的域名,然後再向這台CDN 的DNS 服務器發送解析域名的請求,這時候它就可以根據ip 所在城市來返回一個就近城市的服務器給你。

當然,也可以再做一層CNAME 轉發,比如CDN 的DNS 服務器把域名解析轉給城市的DNS 服務器,然后城市的DNS 服務器再根據不同機器的負載情況來返回一台離得近而且負載比較小的服務器的ip 給客戶端。

這樣客戶端就能從最近的服務器下載靜態資源,從而更快地打開網站。

如果訪問的資源沒有的時候,會向源站服務器發請求來拿對應的資源並且緩存下來,之後再此訪問就不用訪問源站了。

這個緩存時間是怎麼指定的呢?

圖片

CDN 服務會有一個控制台,可以設置不同資源的緩存時間,當然,請求的header 裡也有expries 和Cache-Control 來控制緩存時間,這倆的生效的優先級也是可以設置的。

這樣的CDN 服務國內和國外是分開的,如果網站目標用戶只是國內的,那隻需要買下國內的CDN 服務,國外用戶訪問慢點就慢點,如果網站國外用戶也很多,那還需要買下國外的CDN 服務。

比如某雲的國內CDN 節點分佈是這樣的:

圖片

海外的話則是另一套CDN 網絡:

圖片

總結

為了加快網站打開速度,我們會使用CDN 服務,它並不是一個網絡協議,只是基於DNS 協議實現的加速功能的網絡。

它的原理就是域名的權威DNS 服務器把請求轉給CND 的負載均衡的DNS 服務器,然後根據ip返回不同城市的DNS 服務器,再根據負載來選擇一台就近的服務器的ip 返回。

這樣客戶端就能從最近的負載最小的服務器拿到資源。

CDN 的緩存設置可以根據header 來,也可以在控制台設置一些規則,這兩者生效的優先級也可以設置。

CDN 網絡的建設成本還是很大的,只有大公司會自建,一般我們都會買三方服務,而且國內和海外的CDN 都是分開的,如果主要服務國內用戶,那隻買國內的CDN 服務即可。

有了這套覆蓋全國、全球的CDN 節點網絡之後,我們才能更快地打開網站。