一篇文章讓你搞懂到底什么是 CDN
當(dāng)我們打開(kāi)瀏覽器訪問(wèn)頁(yè)面的時(shí)候,其實(shí)就是一個(gè)不斷發(fā)送 HTTP 請(qǐng)求的過(guò)程,客戶端發(fā)送 HTTP 請(qǐng)求,服務(wù)端返回響應(yīng)。
這里的客戶端可以是瀏覽器,也可以是我們使用 Python 編寫(xiě)的代碼,而服務(wù)端則是使用 Web 框架編寫(xiě)的應(yīng)用程序。
說(shuō)到這兒,補(bǔ)充一個(gè)知識(shí)點(diǎn),很多搞 Python 的小伙伴可能分不清 WSGI, uwsgi, uWSGI, Nginx 之間的區(qū)別,我們來(lái)總結(jié)一下。
WSGI
WSGI 的全稱是 Web Server Gateway Interface,即 Web 服務(wù)器網(wǎng)關(guān)接口,它不是服務(wù)器,也不是 Python 模塊、框架、或者任何軟件,它只是一種描述 Web 服務(wù)器和 Web 應(yīng)用程序(使用 Web 框架編寫(xiě)的程序)進(jìn)行通信的規(guī)范、協(xié)議。
基于 Web 框架編寫(xiě)的服務(wù)要運(yùn)行在 Web 服務(wù)器上,盡管這些框架本身自帶了一個(gè)小型 Web 服務(wù)器,但只用于開(kāi)發(fā)和測(cè)試。
uWSGI
uWSGI 是一個(gè) Web 服務(wù)器,它實(shí)現(xiàn)了 WSGI, uwsgi, HTTP 等協(xié)議,所以我們把使用 Web 框架編寫(xiě)好的服務(wù)部署在 uWSGI 上面,是可以直接對(duì)外提供服務(wù)的。
Nginx
同樣是一個(gè) Web 服務(wù)器,但它相比 uWSGI 可以提供更多的功能,比如反向代理、負(fù)載均衡、緩存靜態(tài)資源、對(duì) HTTP 請(qǐng)求更加友好,這些都是 uWSGI 所不具備、或者不擅長(zhǎng)的。
所以將 Web 服務(wù)部署在 uWSGI 之后,還要在前面再搭一層 Nginx。此時(shí) uWSGI 就不再暴露 HTTP 服務(wù)了,而是暴露 TCP 服務(wù),因?yàn)樗呛?Nginx 進(jìn)行通信,使用 TCP 會(huì)更快一些,Nginx 來(lái)對(duì)外暴露 HTTP 服務(wù)。
uwsgi
uwsgi 是 Nginx 和 uWSGI 通信所采用的協(xié)議,我們說(shuō) uWSGI 是和 Nginx 對(duì)接。
Nginx 在接收到用戶請(qǐng)求后,如果請(qǐng)求的是圖片等靜態(tài)資源,那么可以直接返回。請(qǐng)求的是動(dòng)態(tài)資源,那么會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給 uWSGI,然后再由 uWSGI 調(diào)用相應(yīng)的 Web 服務(wù)進(jìn)行處理,處理完畢之后將結(jié)果交給 Nginx,Nginx 再返回給客戶端。
而 uWSGI 和 Nginx 之所以能交互,也正是因?yàn)樗鼈兌贾С?uwsgi 協(xié)議,Nginx 內(nèi)部有一個(gè)模塊叫 HttpUwsgiModule,它的作用就是與 uWSGI 服務(wù)器進(jìn)行交互。
回到正題,我們知道 HTTP 是請(qǐng)求-響應(yīng)模型,當(dāng)使用瀏覽器打開(kāi)一個(gè)頁(yè)面時(shí),瀏覽器和目標(biāo)服務(wù)器便是 HTTP 協(xié)議的兩個(gè)端點(diǎn)。
那么問(wèn)題來(lái)了,瀏覽器發(fā)出的請(qǐng)求,一定要直接到達(dá)指定的目標(biāo)服務(wù)器嗎?可不可以在其它地方先逗留一下呢?答案是可以的,這個(gè)地方就是代理。
在 HTTP 協(xié)議中,代理(Proxy)是請(qǐng)求方和應(yīng)答方中間的一個(gè)環(huán)節(jié)。作為中轉(zhuǎn)站,既可以轉(zhuǎn)發(fā)客戶端的請(qǐng)求,也可以轉(zhuǎn)發(fā)服務(wù)器的應(yīng)答。代理的種類(lèi)很多,常見(jiàn)的有:
- 匿名代理:完全隱匿了被代理的機(jī)器,外界看到的只是代理服務(wù)器
- 透明代理:顧名思義,它在傳輸過(guò)程中是透明開(kāi)放的,外界既知道代理,也知道客戶端
- 正向代理:靠近客戶端,代表客戶端向服務(wù)器發(fā)送請(qǐng)求
- 反向代理:靠近服務(wù)器,代表服務(wù)器向客戶端返回響應(yīng)
關(guān)于正向代理和反向代理,我們?cè)倥e兩個(gè)例子解釋一下。
正向代理
假設(shè)你想找 B 借一樣?xùn)|西,但是 B 不同意,于是你拜托 A 去從 B 那里借,然后再交給你。這里的 A 就扮演了代理的角色,也是正向代理,因?yàn)檎嬲?B 借東西的是 A。
如果 A 在找 B 借東西的時(shí)候沒(méi)有說(shuō)這是你想借的,那么 A 就是匿名代理,因?yàn)?B 不知道你的存在;如果 A 告訴了 B,其實(shí)是你拜托他來(lái)找 B 的,那么 A 就是透明代理,B 知道 A,同時(shí)也知道你。
像我們平常掛的 V批N 就是正向代理,當(dāng)你訪問(wèn)谷歌卻慘遭拒絕時(shí),你可以讓 V批N 去幫你訪問(wèn)。而對(duì)于谷歌而言,向它發(fā)請(qǐng)求的是 V批N,不是你。
反向代理
反向代理也很簡(jiǎn)單,比如訪問(wèn)百度,其背后可能有千千萬(wàn)萬(wàn)臺(tái)服務(wù)器在提供服務(wù),但我們不會(huì)直接訪問(wèn)它們,而是訪問(wèn)反向代理服務(wù)器。
www.baidu.com 所在的就是代理服務(wù)器,它會(huì)幫我們把請(qǐng)求轉(zhuǎn)發(fā)到真實(shí)的服務(wù)器那里去。像 Nginx 就是一個(gè)非常好的反向代理服務(wù)器,可以對(duì)背后所有真實(shí)的服務(wù)器進(jìn)行一個(gè)權(quán)衡,將請(qǐng)求轉(zhuǎn)發(fā)到一個(gè)合適的服務(wù)器上,也就是所謂的負(fù)載均衡。
再比如小明同學(xué)聯(lián)系老鴇,希望她能提供一個(gè)小姐姐上門(mén)幫忙補(bǔ)習(xí)外語(yǔ),這個(gè)老鴇就是反向代理,她會(huì)將小明的請(qǐng)求轉(zhuǎn)發(fā)到某一個(gè)小姐姐那里去。
所以正向代理和反向代理都屬于代理,而核心區(qū)別就在于代理的對(duì)象不同:正向代理代理的是客戶端,負(fù)責(zé)向服務(wù)端發(fā)送請(qǐng)求;反向代理代理的是服務(wù)端,負(fù)責(zé)向客戶端返回響應(yīng)。
由于代理在傳輸過(guò)程中插入了一個(gè)中間層,因此可以在這個(gè)環(huán)節(jié)做很多有意思的事情,比如:
- 負(fù)載均衡:把訪問(wèn)的請(qǐng)求均勻分散到多臺(tái)機(jī)器,實(shí)現(xiàn)訪問(wèn)集群化
- 內(nèi)容緩存:暫存上下行的數(shù)據(jù),減輕后端的壓力
- 安全防護(hù):隱匿 IP,使用 WAF 等工具抵御網(wǎng)絡(luò)攻擊,保護(hù)被代理的機(jī)器
- 數(shù)據(jù)處理:提供壓縮、加密等額外的功能
了解了以上內(nèi)容,就能很清楚地知道什么是 CDN 了。
CDN 的全稱為 Content Delivery Network,翻譯過(guò)來(lái)就是內(nèi)容分發(fā)網(wǎng)絡(luò),它應(yīng)用了 HTTP 協(xié)議里的緩存和代理技術(shù),代替源站服務(wù)器響應(yīng)客戶端的請(qǐng)求。所以 CDN 也屬于代理,并且通常扮演透明代理和反向代理的角色。
說(shuō)白了就是它可以緩存源站的數(shù)據(jù),讓瀏覽器的請(qǐng)求不用千里迢迢地到達(dá)源站服務(wù)器,直接在半路就可以獲取響應(yīng)。如果 CDN 的調(diào)度算法很優(yōu)秀,那么就可以找到離用戶最近的節(jié)點(diǎn),大幅度縮短響應(yīng)時(shí)間。
因?yàn)樵诂F(xiàn)如今這個(gè)信息量爆炸的時(shí)代,用戶等待的耐心也越來(lái)越低,有一個(gè)說(shuō)法:當(dāng)用戶打開(kāi)一個(gè)頁(yè)面,如果超過(guò) 4 秒沒(méi)有響應(yīng),他就會(huì)關(guān)閉這個(gè)頁(yè)面。所以任何一個(gè)服務(wù)提供商,都希望自己服務(wù)的響應(yīng)速度足夠快,這樣才能留住用戶。
而用戶從發(fā)出請(qǐng)求到接收響應(yīng)所消耗的時(shí)間不僅取決于網(wǎng)絡(luò)帶寬,還取決于傳輸距離。比如服務(wù)器在廣東,但訪問(wèn)的用戶在北京,地理位置的距離會(huì)導(dǎo)致延遲變得明顯,而且傳輸距離過(guò)長(zhǎng)也會(huì)導(dǎo)致數(shù)據(jù)包丟失可能性變大,導(dǎo)致網(wǎng)絡(luò)中斷。
所以 CDN 便誕生了,它是專門(mén)負(fù)責(zé)解決長(zhǎng)距離導(dǎo)致網(wǎng)絡(luò)訪問(wèn)速度慢的一種應(yīng)用服務(wù)。其最初的核心理念就是將內(nèi)容緩存在終端用戶附近,源站不是離用戶遠(yuǎn)嗎,沒(méi)關(guān)系,在靠近用戶的地方建立一個(gè)緩存服務(wù)器,將源站的內(nèi)容拷貝一份放在這里不就行了。
后續(xù)北京的用戶訪問(wèn)北京的緩存服務(wù)器,上海用戶訪問(wèn)上海的緩存服務(wù)器。沒(méi)錯(cuò),這便是 CDN 的核心思想,只是建立緩存服務(wù)器需要大量資金,很多公司一般不會(huì)自己這么干,而是購(gòu)買(mǎi)現(xiàn)有的 CDN 服務(wù)。
有很多 CDN 廠商投入了大筆資金,在全國(guó)、乃至全球的各個(gè)大樞紐城市都建立了機(jī)房,部署了大量擁有高存儲(chǔ)高帶寬的節(jié)點(diǎn),構(gòu)建了一個(gè)專用網(wǎng)絡(luò)。這個(gè)網(wǎng)絡(luò)是跨運(yùn)營(yíng)商、跨地域的,雖然內(nèi)部也劃分成多個(gè)小網(wǎng)絡(luò),但它們之間用高速專有線路連接,是真正的信息高速公路,基本上可以認(rèn)為不存在網(wǎng)絡(luò)擁堵。
有了高速的網(wǎng)絡(luò)傳輸通道后,CDN 就要分發(fā)源站的內(nèi)容了,采用緩存代理技術(shù),使用推或拉的手段,將源站的內(nèi)容逐級(jí)緩存到網(wǎng)絡(luò)的每一個(gè)節(jié)點(diǎn)上。由于整個(gè)過(guò)程相當(dāng)于通過(guò)網(wǎng)絡(luò)對(duì)內(nèi)容做了分發(fā),因此叫 CDN,即內(nèi)容分發(fā)網(wǎng)絡(luò)。
具體來(lái)說(shuō),CDN 就是采用更多的緩存服務(wù)器(也叫 CDN 節(jié)點(diǎn)),當(dāng)用戶訪問(wèn)網(wǎng)站時(shí),利用全局負(fù)載技術(shù),將用戶的請(qǐng)求轉(zhuǎn)發(fā)到距離最近的 CDN 節(jié)點(diǎn)(術(shù)語(yǔ)叫邊緣節(jié)點(diǎn))上,由緩存服務(wù)器響應(yīng)用戶請(qǐng)求。這樣一來(lái)就省去了長(zhǎng)途跋涉的時(shí)間成本,實(shí)現(xiàn)了網(wǎng)絡(luò)加速。
那么 CDN 都能加速什么樣的內(nèi)容呢?或者說(shuō) CDN 節(jié)點(diǎn)應(yīng)該保存哪些內(nèi)容呢?
在 CDN 領(lǐng)域,內(nèi)容其實(shí)就是 HTTP 協(xié)議里的資源,比如超文本、圖片、視頻等。資源按照是否可以緩存,分為靜態(tài)資源和動(dòng)態(tài)資源兩類(lèi)。
- 靜態(tài)資源:數(shù)據(jù)內(nèi)容靜態(tài)不變,任何時(shí)候來(lái)訪問(wèn)都是一樣的,比如圖片、音頻。
- 動(dòng)態(tài)資源:數(shù)據(jù)內(nèi)容動(dòng)態(tài)變化,即內(nèi)容由后臺(tái)服務(wù)計(jì)算生成,每次訪問(wèn)都可能發(fā)生變化,比如商品的庫(kù)存、微博的粉絲數(shù)等。
很顯然,只有靜態(tài)資源才能夠被緩存加速、就近訪問(wèn),而動(dòng)態(tài)資源只能由源站實(shí)時(shí)生成,即使緩存了也沒(méi)有意義。不過(guò),如果動(dòng)態(tài)資源在一段時(shí)間內(nèi)不會(huì)發(fā)生變化,那么可以在響應(yīng)頭中指定 Cache-Control 字段,表示允許緩存一段短暫的時(shí)間,那么它在這段時(shí)間里也就變成了靜態(tài)資源,可以被 CDN 緩存加速。
CDN:我們不生產(chǎn)內(nèi)容,我們只做內(nèi)容的搬運(yùn)工。
到目前為止,我們已經(jīng)知道 CDN 到底是啥了,然后再來(lái)看看它是怎么運(yùn)行的。CDN 有兩個(gè)關(guān)鍵組成部分:全局負(fù)載均衡和緩存系統(tǒng)。
全局負(fù)載均衡
全局負(fù)載均衡(Global Sever Load Balance)一般簡(jiǎn)稱為 GSLB,它是 CDN 的大腦。主要的職責(zé)是當(dāng)用戶接入網(wǎng)絡(luò)的時(shí)候,在 CDN 專網(wǎng)中挑選出一個(gè)最佳節(jié)點(diǎn)提供服務(wù),解決的是如何找到最近的節(jié)點(diǎn),即邊緣節(jié)點(diǎn),負(fù)責(zé)對(duì)整個(gè) CDN 網(wǎng)絡(luò)進(jìn)行負(fù)載均衡。
GSLB 最常見(jiàn)的實(shí)現(xiàn)方式是 DNS 負(fù)載均衡,不過(guò) GSLB 的方式要略微復(fù)雜一些。
首先在沒(méi)有 CDN 的時(shí)候,權(quán)威 DNS 返回的就是源站服務(wù)器的實(shí)際 IP 地址,瀏覽器收到 DNS 解析結(jié)果后直連即可。但加入 CDN 就不一樣了,權(quán)威 DNS 返回的不再是 IP 地址,而是一個(gè) CNAME(Canonical Name)別名記錄,指向的就是 CDN 的 GSLB。
意思就是我沒(méi)法給你源站服務(wù)器的 IP,給你的是 GSLB,你需要再去 GSLB 查一下。因?yàn)闆](méi)拿到 IP 地址,于是本地 DNS 就會(huì)向 GSLB 再發(fā)起請(qǐng)求,這樣就進(jìn)入了 CDN 的全局負(fù)載均衡系統(tǒng),基于以下原則開(kāi)始智能調(diào)度:
- 看用戶的 IP 地址,查表得知地理位置,找相對(duì)最近的邊緣節(jié)點(diǎn)。比如 IP 是北京,那么就找北京的邊緣節(jié)點(diǎn);
- 看用戶所在的運(yùn)營(yíng)商網(wǎng)絡(luò),找相同網(wǎng)絡(luò)的邊緣節(jié)點(diǎn),因?yàn)檫吘壒?jié)點(diǎn)不止一個(gè),但選擇網(wǎng)絡(luò)相同的更有優(yōu)勢(shì);
- 檢查邊緣節(jié)點(diǎn)的負(fù)載情況,找負(fù)載較輕的節(jié)點(diǎn);
- 參考節(jié)點(diǎn)的健康狀況、服務(wù)能力、帶寬、響應(yīng)時(shí)間等;
GSLB 把這些因素綜合起來(lái),用一個(gè)復(fù)雜的算法,最后找出一臺(tái)最合適的邊緣節(jié)點(diǎn),把這個(gè)節(jié)點(diǎn)的 IP 地址返回給用戶,用戶就可以就近訪問(wèn) CDN 的緩存代理了。
緩存系統(tǒng)
緩存系統(tǒng)是 CDN 的另一個(gè)關(guān)鍵組成部分,相當(dāng)于 CDN 的心臟。如果緩存系統(tǒng)的服務(wù)能力不夠,不能很好地滿足用戶的需求,那 GSLB 調(diào)度算法再優(yōu)秀也沒(méi)有用。
但互聯(lián)網(wǎng)上的資源是無(wú)窮無(wú)盡的,不管 CDN 廠商有多大的實(shí)力,都不可能把所有資源都緩存起來(lái)。所以,緩存系統(tǒng)只能有選擇地緩存那些最常用的資源,于是便產(chǎn)生了 CDN 中的兩個(gè)關(guān)鍵概念:命中和回源。
命中就是指用戶訪問(wèn)的資源恰好在緩存系統(tǒng)里,可以直接返回給用戶。回源則正相反,緩存里沒(méi)有,代理必須先將數(shù)據(jù)從源站同步過(guò)來(lái)。
相應(yīng)的,衡量 CND 服務(wù)質(zhì)量的兩個(gè)指標(biāo)便是命中率和回源率,計(jì)算方式為命中次數(shù) / 回源次數(shù)除以總訪問(wèn)次數(shù)。顯然,好的 CDN 應(yīng)該是命中率越高越好,回源率越低越好?,F(xiàn)在的商業(yè) CDN 命中率都在 90% 以上,相當(dāng)于把源站的服務(wù)能力放大了 10 倍以上。
那怎樣才能盡可能地提高命中率、降低回源率呢?
首先肯定是在存儲(chǔ)系統(tǒng)上下功夫,盡可能存儲(chǔ)更多的內(nèi)容。
其次,緩存也可以劃分層級(jí),分為一級(jí)緩存和二級(jí)緩存。一級(jí)緩存配置高一些,直連源站,二級(jí)緩存配置低一些,直連用戶?;卦吹臅r(shí)候,二級(jí)緩存只找一級(jí)緩存,一級(jí)緩存沒(méi)有再回源。這樣扇入便縮小了,可以有效地減少回源。
CDN 雖然有很多的優(yōu)點(diǎn),但它不是萬(wàn)能的。
如果是用戶動(dòng)態(tài)交互的實(shí)時(shí)數(shù)據(jù),那么很難緩存在 CDN 中。
另外很多公司為了保護(hù)自身的數(shù)據(jù)隱私,不允許第三方 CDN 廠商緩存數(shù)據(jù),只允許自家 CDN 緩存,這個(gè)可能會(huì)造成一些影響。
然后就是最關(guān)鍵的,如果是自建 CDN,那么非常燒錢(qián),因此大部分公司都不會(huì)自建,而是選擇專門(mén)的 CDN 廠商。但即便是租用 CDN 服務(wù),花的錢(qián)也不少,區(qū)域越多花的錢(qián)也越多。
CDN 和邊緣計(jì)算
互聯(lián)網(wǎng)公司采用 CDN 是用存儲(chǔ)空間換網(wǎng)絡(luò)低延遲,但很多通信公司也青睞 CDN,目的則是以存儲(chǔ)空間換網(wǎng)絡(luò)帶寬。通過(guò)服務(wù)下沉,減輕上層骨干網(wǎng)絡(luò)的流量壓力,避免硬件擴(kuò)容,降低網(wǎng)絡(luò)建設(shè)成本。因?yàn)榇罅康臉I(yè)務(wù)流量數(shù)據(jù)在骨干網(wǎng)跑來(lái)跑去,骨干網(wǎng)肯定吃不消,要拼命擴(kuò)容。但如果這些業(yè)務(wù)流量數(shù)據(jù)在底層就被解決了,那么骨干網(wǎng)的帶寬壓力自然就減輕了。
很多運(yùn)營(yíng)商已經(jīng)將 CDN 下沉到地市級(jí),以此減輕壓力,同時(shí)可以提升用戶體驗(yàn)。說(shuō)到這,你應(yīng)該想到了邊緣計(jì)算,有很多人覺(jué)得 CDN 和邊緣計(jì)算很相似,因?yàn)?CDN 算是邊緣計(jì)算的雛形。
一直以來(lái),隨著網(wǎng)絡(luò)能力的不斷提升,內(nèi)容資源和計(jì)算能力都在不斷往上走,走到云計(jì)算中心。通過(guò)核心的云計(jì)算中心,對(duì)所有終端節(jié)點(diǎn)提供服務(wù)。但隨著用戶量的增加,用戶所在區(qū)域和計(jì)算中心可能距離很遠(yuǎn),那么不管把計(jì)算中心設(shè)置在什么地方,也不管它的能力有多強(qiáng)大,都無(wú)法克服物理距離上的障礙。
于是人們便想到,數(shù)據(jù)能不能不要上傳到計(jì)算中心,而是轉(zhuǎn)移到網(wǎng)絡(luò)的邊緣,即數(shù)據(jù)輸入的地方(例如 IoT 設(shè)備),然后直接計(jì)算呢?于是便有了邊緣計(jì)算,它不會(huì)將數(shù)據(jù)發(fā)送到計(jì)算中心進(jìn)行處理,而是在數(shù)據(jù)源附近處理數(shù)據(jù)。
所以 CDN 和邊緣計(jì)算還是有差異的:
- CDN 負(fù)責(zé)優(yōu)化數(shù)據(jù)交付;邊緣計(jì)算負(fù)責(zé)優(yōu)化數(shù)據(jù)處理
- CDN 通常用于交互靜態(tài)內(nèi)容,例如網(wǎng)頁(yè)、圖片和視頻;邊緣計(jì)算用于需要快速數(shù)據(jù)處理的應(yīng)用,例如實(shí)時(shí)數(shù)據(jù)分析等
- CDN 會(huì)將內(nèi)容放到距離用戶近的地方;邊緣計(jì)算會(huì)將計(jì)算和數(shù)據(jù)處理放到盡可能靠近數(shù)據(jù)產(chǎn)生的地方
但這兩者是可以互補(bǔ)的,比如一個(gè)邊緣計(jì)算設(shè)備可以使用 CDN 來(lái)高效地交互內(nèi)容,同時(shí)在網(wǎng)絡(luò)邊緣處理數(shù)據(jù)。
另外 CDN 也可以使用邊緣計(jì)算,通過(guò)把計(jì)算動(dòng)態(tài)資源的代碼和數(shù)據(jù)也放在 CDN 的節(jié)點(diǎn)上,這樣就可以在 CDN 里獲取動(dòng)態(tài)資源不用回源了。