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