16 | CDN:靜態(tài)資源如何加速?

前面幾節(jié)課,我?guī)懔私饬司彺娴亩x以及常用緩存的使用姿勢,你應(yīng)該對包括本地緩存、分布式緩存等緩存組件的適用場景和使用技巧有了一定了解了。結(jié)合在14 講中我提到的客戶端高可用方案,你會將單個緩存節(jié)點擴展為高可用的緩存集群,現(xiàn)在,你的電商系統(tǒng)架構(gòu)演變成了下面這樣:

img

在這個架構(gòu)中我們使用分布式緩存對動態(tài)請求數(shù)據(jù)的讀取做了加速,但是在我們的系統(tǒng)中存在著大量的靜態(tài)資源請求:

1、對于移動 APP 來說,這些靜態(tài)資源主要是圖片、視頻和流媒體信息;對于 Web 2、網(wǎng)站來說,則包括了 JavaScript 文件、CSS 文件、靜態(tài) HTML 文件等等。

具體到你的電商系統(tǒng)來說,商品的圖片、介紹商品使用方法的視頻等等靜態(tài)資源都放在了 Nginx 等 Web 服務(wù)器上,它們的讀請求量極大并且對訪問速度的要求很高還占據(jù)了很高的帶寬,這時會出現(xiàn)訪問速度慢帶寬被占滿影響動態(tài)請求的問題,那么你就需要考慮如何針對這些靜態(tài)資源進行讀加速了。

靜態(tài)資源加速的考慮點

你可能會問:“我們是否也可以使用分布式緩存來解決這個問題呢?”答案是否定的。一般來說,圖片和視頻的大小會在幾兆到幾百兆之間不等,如果我們的應(yīng)用服務(wù)器和分布式緩存都部署在北京的機房里,這時一個杭州的用戶要訪問緩存中的一個視頻,那這個視頻文件就需要從北京傳輸?shù)胶贾荩陂g會經(jīng)過多個公網(wǎng)骨干網(wǎng)絡(luò),延遲很高,會讓用戶感覺視頻打開很慢,嚴重影響到用戶的使用體驗。

所以,靜態(tài)資源訪問的關(guān)鍵點是就近訪問,即北京用戶訪問北京的數(shù)據(jù),杭州用戶訪問杭州的數(shù)據(jù),這樣才可以達到性能的最優(yōu)。

你可能會說:“那我們在杭州也自建一個機房,讓用戶訪問杭州機房的數(shù)據(jù)就好了呀?!笨捎脩舯椴荚谌珖鞯?,有些應(yīng)用可能還有國外的用戶,我們不可能在每個地域都自建機房,這樣成本太高了。

另外,單個視頻和圖片等靜態(tài)資源很大,并且訪問量又極高,如果使用業(yè)務(wù)服務(wù)器和分布式緩存來承擔這些流量,無論是對于內(nèi)網(wǎng)還是外網(wǎng)的帶寬都會是很大的考驗。

所以我們考慮在業(yè)務(wù)服務(wù)器的上層增加一層特殊的緩存,用來承擔絕大部分對于靜態(tài)資源的訪問,這一層特殊緩存的節(jié)點需要遍布在全國各地,這樣可以讓用戶選擇最近的節(jié)點訪問。緩存的命中率也需要一定的保證,盡量減少訪問資源存儲源站的請求數(shù)量(回源請求)。這一層緩存就是我們這節(jié)課的重點:CDN。

CDN 的關(guān)鍵技術(shù)

CDN(Content Delivery Network/Content Distribution Network,內(nèi)容分發(fā)網(wǎng)絡(luò))。簡單來說,CDN 就是將靜態(tài)的資源分發(fā)到位于多個地理位置機房中的服務(wù)器上,因此它能很好地解決數(shù)據(jù)就近訪問的問題,也就加快了靜態(tài)資源的訪問速度。

在大中型公司里面,CDN 的應(yīng)用非常普遍,大公司為了提供更穩(wěn)定的 CDN 服務(wù)會選擇自建 CDN,而大部分公司基于成本的考慮還是會選擇專業(yè)的 CDN 廠商,網(wǎng)宿、阿里云、騰訊云、藍汛等等,其中網(wǎng)宿和藍汛是老牌的 CDN 廠商,阿里云和騰訊云是云廠商提供的服務(wù),如果你的服務(wù)部署在云上可以選擇相應(yīng)云廠商的 CDN 服務(wù),這些 CDN 廠商都是現(xiàn)今行業(yè)內(nèi)比較主流的。

對于 CDN 來說,你可能已經(jīng)從運維的口中聽說過,并且也了解了它的作用。但是當讓你來配置 CDN 或者是排查 CDN 方面的問題時,你就有可能因為不了解它的原理而束手無策了。

所以我先來帶你了解一下搭建一個 CDN 系統(tǒng)需要考慮哪兩點:

  1. 如何將用戶的請求映射到 CDN 節(jié)點上;
  2. 如何根據(jù)用戶的地理位置信息選擇到比較近的節(jié)點。

如何讓用戶的請求到達 CDN 節(jié)點

首先,我們考慮一下如何讓用戶的請求到達 CDN 節(jié)點,你可能會覺得這很簡單啊,只需要告訴用戶 CDN 節(jié)點的 IP 地址,然后請求這個 IP 地址上面部署的 CDN 服務(wù)就可以了啊。但是這樣會有一個問題:就是我們使用的是第三方廠商的 CDN 服務(wù),CDN 廠商會給我們一個 CDN 的節(jié)點 IP,比如說這個 IP 地址是“111.202.34.130”,那么我們的電商系統(tǒng)中的圖片的地址很可能是這樣的:“http://111.202.34.130/1.jpg”, 這個地址是要存儲在數(shù)據(jù)庫中的。

那么如果這個節(jié)點 IP 發(fā)生了變更怎么辦?或者我們?nèi)绻牧?CDN 廠商怎么辦?是不是要修改所有的商品的 url 域名呢?這就是一個比較大的工作量了。所以,我們要做的事情是將第三方廠商提供的 IP 隱藏起來,給到用戶的最好是一個本公司域名的子域名。

那么如何做到這一點呢?這就需要依靠 DNS 來幫我們解決域名映射的問題了。

DNS(Domain Name System,域名系統(tǒng))實際上就是一個存儲域名和 IP 地址對應(yīng)關(guān)系的分布式數(shù)據(jù)庫。而域名解析的結(jié)果一般有兩種,一種叫做“A 記錄”,返回的是域名對應(yīng)的 IP 地址;另一種是“CNAME 記錄”,返回的是另一個域名,也就是說當前域名的解析要跳轉(zhuǎn)到另一個域名的解析上。實際上 www.baidu.com 域名的解析結(jié)果就是一個 CNAME 記錄,域名的解析被跳轉(zhuǎn)到 www.a.shifen.com 上了,我們正是利用 CNAME 記錄來解決域名映射問題的,具體是怎么解決的呢?我給你舉個例子。

比如你的公司的一級域名叫做 example.com,那么你可以把你的圖片服務(wù)的域名定義為“img.example.com”,然后將這個域名的解析結(jié)果的 CNAME 配置到 CDN 提供的域名上,比如 uclound 可能會提供一個域名是“80f21f91.cdn.ucloud.com.cn”這個域名。這樣你的電商系統(tǒng)使用的圖片地址可以是“http://img.example.com/1.jpg”。

用戶在請求這個地址時,DNS 服務(wù)器會將域名解析到 80f21f91.cdn.ucloud.com.cn 域名上,然后再將這個域名解析為 CDN 的節(jié)點 IP,這樣就可以得到 CDN 上面的資源數(shù)據(jù)了。

不過這里面有一個問題:因為域名解析過程是分級的,每一級有專門的域名服務(wù)器承擔解析的職責,所以域名的解析過程有可能需要跨越公網(wǎng)做多次 DNS 查詢,在性能上是比較差的。

img

從“ 域名分級解析示意圖”中你可以看出 DNS 分為很多種,有根 DNS,頂級 DNS 等等。除此之外還有兩種 DNS 需要特別留意:一種是 Local DNS,它是由你的運營商提供的 DNS,一般域名解析的第一站會到這里;另一種是權(quán)威 DNS,它的含義是自身數(shù)據(jù)庫中存儲了這個域名對應(yīng)關(guān)系的 DNS。

下面我以 www.baidu.com 這個域名為例給你簡單介紹一下域名解析的過程:

  • 一開始,域名解析請求先會檢查本機的 hosts 文件,查看是否有 www.baidu.com 對應(yīng)的 IP;
  • 如果沒有的話,就請求 Local DNS 是否有域名解析結(jié)果的緩存,如果有就返回標識是從非權(quán)威 DNS 返回的結(jié)果;
  • 如果沒有就開始 DNS 的迭代查詢。先請求根 DNS,根 DNS 返回頂級 DNS(.com)的地址;再請求.com 頂級 DNS 得到 baidu.com 的域名服務(wù)器地址;再從 baidu.com 的域名服務(wù)器中查詢到 www.baidu.com 對應(yīng)的 IP 地址,返回這個 IP 地址的同時標記這個結(jié)果是來自于權(quán)威 DNS 的結(jié)果,同時寫入 Local DNS 的解析結(jié)果緩存,這樣下一次的解析同一個域名就不需要做 DNS 的迭代查詢了。
  • 經(jīng)過了向多個 DNS 服務(wù)器做查詢之后,整個 DNS 的解析的時間有可能會到秒級別,那么我們?nèi)绾蝸斫鉀Q這個性能問題呢?

一個解決的思路是:在 APP 啟動時對需要解析的域名做預先解析,然后把解析的結(jié)果緩存到本地的一個 LRU 緩存里面。這樣當我們要使用這個域名的時候,只需要從緩存中直接拿到所需要的 IP 地址就好了,如果緩存中不存在才會走整個 DNS 查詢的過程。同時為了避免 DNS 解析結(jié)果的變更造成緩存內(nèi)數(shù)據(jù)失效,我們可以啟動一個定時器定期地更新緩存中的數(shù)據(jù)。

我曾經(jīng)測試過這種方式,對于 HTTP 請求的響應(yīng)時間的提升是很明顯的,原先 DNS 解析時間經(jīng)常會超過 1s,使用這種方式后,DNS 解析時間可以控制在 200ms 之內(nèi),整個 HTTP 請求的過程也可以減少大概 80ms~100ms。

img

這里總結(jié)一下,將用戶的請求映射到 CDN 服務(wù)器上是使用 CDN 時需要解決的一個核心的問題,而 CNAME 記錄在 DNS 解析過程中可以充當一個中間代理層的角色,可以把用戶最初使用的域名代理到正確的 IP 地址上。

img

現(xiàn)在,剩下的一個問題就是如何找到更近的 CDN 節(jié)點了,而 GSLB 承擔了這個職責。

如何找到離用戶最近的 CDN 節(jié)點

GSLB(Global Server Load Balance,全局負載均衡)的含義是對于部署在不同地域的服務(wù)器之間做負載均衡,下面可能管理了很多的本地負載均衡組件。它有兩方面的作用:

一方面,它是一種負載均衡服務(wù)器,負載均衡,顧名思義嘛,指的是讓流量平均分配使得下面管理的服務(wù)器的負載更平均;

另一方面,它還需要保證流量流經(jīng)的服務(wù)器與流量源頭在地緣上是比較接近的。

GSLB 可以通過多種策略來保證返回的 CDN 節(jié)點和用戶盡量保證在同一地緣區(qū)域,比如說可以將用戶的 IP 地址按照地理位置劃分為若干個區(qū)域,然后將 CDN 節(jié)點對應(yīng)到一個區(qū)域上,根據(jù)用戶所在區(qū)域來返回合適的節(jié)點;也可以通過發(fā)送數(shù)據(jù)包測量 RTT 的方式來決定返回哪一個節(jié)點。不過這些原理不是本節(jié)課重點內(nèi)容,你了解一下就可以了,我不做詳細的介紹。

有了 GSLB 之后,節(jié)點的解析過程變成了下圖中的樣子:

img

當然,是否能夠從 CDN 節(jié)點上獲取到資源還取決于 CDN 的同步延時。一般我們會通過 CDN 廠商的接口將靜態(tài)的資源寫入到某一個 CDN 節(jié)點上,再由 CDN 內(nèi)部的同步機制將資源分散同步到每個 CDN 節(jié)點,即使 CDN 內(nèi)部網(wǎng)絡(luò)經(jīng)過了優(yōu)化,這個同步的過程是有延時的,一旦我們無法從選定的 CDN 節(jié)點上獲取到數(shù)據(jù),我們就不得不從源站獲取數(shù)據(jù),而用戶網(wǎng)絡(luò)到源站的網(wǎng)絡(luò)可能會跨越多個主干網(wǎng),這樣不僅性能上有損耗也會消耗源站的帶寬,帶來更高的研發(fā)成本。所以我們在使用 CDN 的時候需要關(guān)注 CDN 的命中率和源站的帶寬情況。

總結(jié)

1.DNS 技術(shù)是 CDN 實現(xiàn)中使用的核心技術(shù),可以將用戶的請求映射到 CDN 節(jié)點上;

2.DNS 解析結(jié)果需要做本地緩存,降低 DNS 解析過程的響應(yīng)時間;

3.GSLB 可以給用戶返回一個離著他更近的節(jié)點,加快靜態(tài)資源的訪問速度。

作為一個服務(wù)端開發(fā)人員,你可能會忽略 CDN 的重要性,對于偶爾出現(xiàn)的 CDN 問題嗤之以鼻,覺得這個不是我們應(yīng)該關(guān)心的內(nèi)容,這種想法是錯的。

CDN 是我們系統(tǒng)的門面,其緩存的靜態(tài)數(shù)據(jù),如圖片和視頻數(shù)據(jù)的請求量很可能是接口請求數(shù)據(jù)的幾倍甚至更高,一旦發(fā)生故障,對于整體系統(tǒng)的影響是巨大的。另外 CDN 的帶寬歷來是我們研發(fā)成本的大頭,尤其是目前處于小視頻和直播風口上,大量的小視頻和直播研發(fā)團隊都在絞盡腦汁地減少 CDN 的成本。由此看出,CDN 是我們整體系統(tǒng)至關(guān)重要的組成部分,而它作為一種特殊的緩存,其命中率和可用性也是我們服務(wù)端開發(fā)人員需要重點關(guān)注的指標。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容