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 節點網絡之後,我們才能更快地打開網站。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/c9JZSkGPWvK5n4NVfK5sKg