一篇文章讓你搞懂到底什么是 CDN
當我們打開瀏覽器訪問頁面的時候,其實就是一個不斷發(fā)送 HTTP 請求的過程,客戶端發(fā)送 HTTP 請求,服務端返回響應。

這里的客戶端可以是瀏覽器,也可以是我們使用 Python 編寫的代碼,而服務端則是使用 Web 框架編寫的應用程序。
說到這兒,補充一個知識點,很多搞 Python 的小伙伴可能分不清 WSGI, uwsgi, uWSGI, Nginx 之間的區(qū)別,我們來總結一下。
WSGI
WSGI 的全稱是 Web Server Gateway Interface,即 Web 服務器網關接口,它不是服務器,也不是 Python 模塊、框架、或者任何軟件,它只是一種描述 Web 服務器和 Web 應用程序(使用 Web 框架編寫的程序)進行通信的規(guī)范、協(xié)議。
基于 Web 框架編寫的服務要運行在 Web 服務器上,盡管這些框架本身自帶了一個小型 Web 服務器,但只用于開發(fā)和測試。
uWSGI
uWSGI 是一個 Web 服務器,它實現(xiàn)了 WSGI, uwsgi, HTTP 等協(xié)議,所以我們把使用 Web 框架編寫好的服務部署在 uWSGI 上面,是可以直接對外提供服務的。
Nginx
同樣是一個 Web 服務器,但它相比 uWSGI 可以提供更多的功能,比如反向代理、負載均衡、緩存靜態(tài)資源、對 HTTP 請求更加友好,這些都是 uWSGI 所不具備、或者不擅長的。
所以將 Web 服務部署在 uWSGI 之后,還要在前面再搭一層 Nginx。此時 uWSGI 就不再暴露 HTTP 服務了,而是暴露 TCP 服務,因為它是和 Nginx 進行通信,使用 TCP 會更快一些,Nginx 來對外暴露 HTTP 服務。
uwsgi
uwsgi 是 Nginx 和 uWSGI 通信所采用的協(xié)議,我們說 uWSGI 是和 Nginx 對接。
Nginx 在接收到用戶請求后,如果請求的是圖片等靜態(tài)資源,那么可以直接返回。請求的是動態(tài)資源,那么會將請求轉發(fā)給 uWSGI,然后再由 uWSGI 調用相應的 Web 服務進行處理,處理完畢之后將結果交給 Nginx,Nginx 再返回給客戶端。
而 uWSGI 和 Nginx 之所以能交互,也正是因為它們都支持 uwsgi 協(xié)議,Nginx 內部有一個模塊叫 HttpUwsgiModule,它的作用就是與 uWSGI 服務器進行交互。
回到正題,我們知道 HTTP 是請求-響應模型,當使用瀏覽器打開一個頁面時,瀏覽器和目標服務器便是 HTTP 協(xié)議的兩個端點。

那么問題來了,瀏覽器發(fā)出的請求,一定要直接到達指定的目標服務器嗎?可不可以在其它地方先逗留一下呢?答案是可以的,這個地方就是代理。
在 HTTP 協(xié)議中,代理(Proxy)是請求方和應答方中間的一個環(huán)節(jié)。作為中轉站,既可以轉發(fā)客戶端的請求,也可以轉發(fā)服務器的應答。代理的種類很多,常見的有:
- 匿名代理:完全隱匿了被代理的機器,外界看到的只是代理服務器
- 透明代理:顧名思義,它在傳輸過程中是透明開放的,外界既知道代理,也知道客戶端
- 正向代理:靠近客戶端,代表客戶端向服務器發(fā)送請求
- 反向代理:靠近服務器,代表服務器向客戶端返回響應
關于正向代理和反向代理,我們再舉兩個例子解釋一下。
正向代理
假設你想找 B 借一樣東西,但是 B 不同意,于是你拜托 A 去從 B 那里借,然后再交給你。這里的 A 就扮演了代理的角色,也是正向代理,因為真正找 B 借東西的是 A。
如果 A 在找 B 借東西的時候沒有說這是你想借的,那么 A 就是匿名代理,因為 B 不知道你的存在;如果 A 告訴了 B,其實是你拜托他來找 B 的,那么 A 就是透明代理,B 知道 A,同時也知道你。
像我們平常掛的 V批N 就是正向代理,當你訪問谷歌卻慘遭拒絕時,你可以讓 V批N 去幫你訪問。而對于谷歌而言,向它發(fā)請求的是 V批N,不是你。
反向代理
反向代理也很簡單,比如訪問百度,其背后可能有千千萬萬臺服務器在提供服務,但我們不會直接訪問它們,而是訪問反向代理服務器。
www.baidu.com 所在的就是代理服務器,它會幫我們把請求轉發(fā)到真實的服務器那里去。像 Nginx 就是一個非常好的反向代理服務器,可以對背后所有真實的服務器進行一個權衡,將請求轉發(fā)到一個合適的服務器上,也就是所謂的負載均衡。
再比如小明同學聯(lián)系老鴇,希望她能提供一個小姐姐上門幫忙補習外語,這個老鴇就是反向代理,她會將小明的請求轉發(fā)到某一個小姐姐那里去。
所以正向代理和反向代理都屬于代理,而核心區(qū)別就在于代理的對象不同:正向代理代理的是客戶端,負責向服務端發(fā)送請求;反向代理代理的是服務端,負責向客戶端返回響應。
由于代理在傳輸過程中插入了一個中間層,因此可以在這個環(huán)節(jié)做很多有意思的事情,比如:
- 負載均衡:把訪問的請求均勻分散到多臺機器,實現(xiàn)訪問集群化
- 內容緩存:暫存上下行的數(shù)據,減輕后端的壓力
- 安全防護:隱匿 IP,使用 WAF 等工具抵御網絡攻擊,保護被代理的機器
- 數(shù)據處理:提供壓縮、加密等額外的功能
了解了以上內容,就能很清楚地知道什么是 CDN 了。
CDN 的全稱為 Content Delivery Network,翻譯過來就是內容分發(fā)網絡,它應用了 HTTP 協(xié)議里的緩存和代理技術,代替源站服務器響應客戶端的請求。所以 CDN 也屬于代理,并且通常扮演透明代理和反向代理的角色。
說白了就是它可以緩存源站的數(shù)據,讓瀏覽器的請求不用千里迢迢地到達源站服務器,直接在半路就可以獲取響應。如果 CDN 的調度算法很優(yōu)秀,那么就可以找到離用戶最近的節(jié)點,大幅度縮短響應時間。
因為在現(xiàn)如今這個信息量爆炸的時代,用戶等待的耐心也越來越低,有一個說法:當用戶打開一個頁面,如果超過 4 秒沒有響應,他就會關閉這個頁面。所以任何一個服務提供商,都希望自己服務的響應速度足夠快,這樣才能留住用戶。
而用戶從發(fā)出請求到接收響應所消耗的時間不僅取決于網絡帶寬,還取決于傳輸距離。比如服務器在廣東,但訪問的用戶在北京,地理位置的距離會導致延遲變得明顯,而且傳輸距離過長也會導致數(shù)據包丟失可能性變大,導致網絡中斷。
所以 CDN 便誕生了,它是專門負責解決長距離導致網絡訪問速度慢的一種應用服務。其最初的核心理念就是將內容緩存在終端用戶附近,源站不是離用戶遠嗎,沒關系,在靠近用戶的地方建立一個緩存服務器,將源站的內容拷貝一份放在這里不就行了。
后續(xù)北京的用戶訪問北京的緩存服務器,上海用戶訪問上海的緩存服務器。沒錯,這便是 CDN 的核心思想,只是建立緩存服務器需要大量資金,很多公司一般不會自己這么干,而是購買現(xiàn)有的 CDN 服務。
有很多 CDN 廠商投入了大筆資金,在全國、乃至全球的各個大樞紐城市都建立了機房,部署了大量擁有高存儲高帶寬的節(jié)點,構建了一個專用網絡。這個網絡是跨運營商、跨地域的,雖然內部也劃分成多個小網絡,但它們之間用高速專有線路連接,是真正的信息高速公路,基本上可以認為不存在網絡擁堵。
有了高速的網絡傳輸通道后,CDN 就要分發(fā)源站的內容了,采用緩存代理技術,使用推或拉的手段,將源站的內容逐級緩存到網絡的每一個節(jié)點上。由于整個過程相當于通過網絡對內容做了分發(fā),因此叫 CDN,即內容分發(fā)網絡。
具體來說,CDN 就是采用更多的緩存服務器(也叫 CDN 節(jié)點),當用戶訪問網站時,利用全局負載技術,將用戶的請求轉發(fā)到距離最近的 CDN 節(jié)點(術語叫邊緣節(jié)點)上,由緩存服務器響應用戶請求。這樣一來就省去了長途跋涉的時間成本,實現(xiàn)了網絡加速。

那么 CDN 都能加速什么樣的內容呢?或者說 CDN 節(jié)點應該保存哪些內容呢?
在 CDN 領域,內容其實就是 HTTP 協(xié)議里的資源,比如超文本、圖片、視頻等。資源按照是否可以緩存,分為靜態(tài)資源和動態(tài)資源兩類。
- 靜態(tài)資源:數(shù)據內容靜態(tài)不變,任何時候來訪問都是一樣的,比如圖片、音頻。
- 動態(tài)資源:數(shù)據內容動態(tài)變化,即內容由后臺服務計算生成,每次訪問都可能發(fā)生變化,比如商品的庫存、微博的粉絲數(shù)等。
很顯然,只有靜態(tài)資源才能夠被緩存加速、就近訪問,而動態(tài)資源只能由源站實時生成,即使緩存了也沒有意義。不過,如果動態(tài)資源在一段時間內不會發(fā)生變化,那么可以在響應頭中指定 Cache-Control 字段,表示允許緩存一段短暫的時間,那么它在這段時間里也就變成了靜態(tài)資源,可以被 CDN 緩存加速。
CDN:我們不生產內容,我們只做內容的搬運工。
到目前為止,我們已經知道 CDN 到底是啥了,然后再來看看它是怎么運行的。CDN 有兩個關鍵組成部分:全局負載均衡和緩存系統(tǒng)。
全局負載均衡
全局負載均衡(Global Sever Load Balance)一般簡稱為 GSLB,它是 CDN 的大腦。主要的職責是當用戶接入網絡的時候,在 CDN 專網中挑選出一個最佳節(jié)點提供服務,解決的是如何找到最近的節(jié)點,即邊緣節(jié)點,負責對整個 CDN 網絡進行負載均衡。
GSLB 最常見的實現(xiàn)方式是 DNS 負載均衡,不過 GSLB 的方式要略微復雜一些。
首先在沒有 CDN 的時候,權威 DNS 返回的就是源站服務器的實際 IP 地址,瀏覽器收到 DNS 解析結果后直連即可。但加入 CDN 就不一樣了,權威 DNS 返回的不再是 IP 地址,而是一個 CNAME(Canonical Name)別名記錄,指向的就是 CDN 的 GSLB。
意思就是我沒法給你源站服務器的 IP,給你的是 GSLB,你需要再去 GSLB 查一下。因為沒拿到 IP 地址,于是本地 DNS 就會向 GSLB 再發(fā)起請求,這樣就進入了 CDN 的全局負載均衡系統(tǒng),基于以下原則開始智能調度:
- 看用戶的 IP 地址,查表得知地理位置,找相對最近的邊緣節(jié)點。比如 IP 是北京,那么就找北京的邊緣節(jié)點;
- 看用戶所在的運營商網絡,找相同網絡的邊緣節(jié)點,因為邊緣節(jié)點不止一個,但選擇網絡相同的更有優(yōu)勢;
- 檢查邊緣節(jié)點的負載情況,找負載較輕的節(jié)點;
- 參考節(jié)點的健康狀況、服務能力、帶寬、響應時間等;
GSLB 把這些因素綜合起來,用一個復雜的算法,最后找出一臺最合適的邊緣節(jié)點,把這個節(jié)點的 IP 地址返回給用戶,用戶就可以就近訪問 CDN 的緩存代理了。

緩存系統(tǒng)
緩存系統(tǒng)是 CDN 的另一個關鍵組成部分,相當于 CDN 的心臟。如果緩存系統(tǒng)的服務能力不夠,不能很好地滿足用戶的需求,那 GSLB 調度算法再優(yōu)秀也沒有用。
但互聯(lián)網上的資源是無窮無盡的,不管 CDN 廠商有多大的實力,都不可能把所有資源都緩存起來。所以,緩存系統(tǒng)只能有選擇地緩存那些最常用的資源,于是便產生了 CDN 中的兩個關鍵概念:命中和回源。
命中就是指用戶訪問的資源恰好在緩存系統(tǒng)里,可以直接返回給用戶。回源則正相反,緩存里沒有,代理必須先將數(shù)據從源站同步過來。
相應的,衡量 CND 服務質量的兩個指標便是命中率和回源率,計算方式為命中次數(shù) / 回源次數(shù)除以總訪問次數(shù)。顯然,好的 CDN 應該是命中率越高越好,回源率越低越好?,F(xiàn)在的商業(yè) CDN 命中率都在 90% 以上,相當于把源站的服務能力放大了 10 倍以上。
那怎樣才能盡可能地提高命中率、降低回源率呢?
首先肯定是在存儲系統(tǒng)上下功夫,盡可能存儲更多的內容。
其次,緩存也可以劃分層級,分為一級緩存和二級緩存。一級緩存配置高一些,直連源站,二級緩存配置低一些,直連用戶?;卦吹臅r候,二級緩存只找一級緩存,一級緩存沒有再回源。這樣扇入便縮小了,可以有效地減少回源。
CDN 雖然有很多的優(yōu)點,但它不是萬能的。
如果是用戶動態(tài)交互的實時數(shù)據,那么很難緩存在 CDN 中。
另外很多公司為了保護自身的數(shù)據隱私,不允許第三方 CDN 廠商緩存數(shù)據,只允許自家 CDN 緩存,這個可能會造成一些影響。
然后就是最關鍵的,如果是自建 CDN,那么非常燒錢,因此大部分公司都不會自建,而是選擇專門的 CDN 廠商。但即便是租用 CDN 服務,花的錢也不少,區(qū)域越多花的錢也越多。
CDN 和邊緣計算
互聯(lián)網公司采用 CDN 是用存儲空間換網絡低延遲,但很多通信公司也青睞 CDN,目的則是以存儲空間換網絡帶寬。通過服務下沉,減輕上層骨干網絡的流量壓力,避免硬件擴容,降低網絡建設成本。因為大量的業(yè)務流量數(shù)據在骨干網跑來跑去,骨干網肯定吃不消,要拼命擴容。但如果這些業(yè)務流量數(shù)據在底層就被解決了,那么骨干網的帶寬壓力自然就減輕了。
很多運營商已經將 CDN 下沉到地市級,以此減輕壓力,同時可以提升用戶體驗。說到這,你應該想到了邊緣計算,有很多人覺得 CDN 和邊緣計算很相似,因為 CDN 算是邊緣計算的雛形。
一直以來,隨著網絡能力的不斷提升,內容資源和計算能力都在不斷往上走,走到云計算中心。通過核心的云計算中心,對所有終端節(jié)點提供服務。但隨著用戶量的增加,用戶所在區(qū)域和計算中心可能距離很遠,那么不管把計算中心設置在什么地方,也不管它的能力有多強大,都無法克服物理距離上的障礙。
于是人們便想到,數(shù)據能不能不要上傳到計算中心,而是轉移到網絡的邊緣,即數(shù)據輸入的地方(例如 IoT 設備),然后直接計算呢?于是便有了邊緣計算,它不會將數(shù)據發(fā)送到計算中心進行處理,而是在數(shù)據源附近處理數(shù)據。
所以 CDN 和邊緣計算還是有差異的:
- CDN 負責優(yōu)化數(shù)據交付;邊緣計算負責優(yōu)化數(shù)據處理
- CDN 通常用于交互靜態(tài)內容,例如網頁、圖片和視頻;邊緣計算用于需要快速數(shù)據處理的應用,例如實時數(shù)據分析等
- CDN 會將內容放到距離用戶近的地方;邊緣計算會將計算和數(shù)據處理放到盡可能靠近數(shù)據產生的地方
但這兩者是可以互補的,比如一個邊緣計算設備可以使用 CDN 來高效地交互內容,同時在網絡邊緣處理數(shù)據。
另外 CDN 也可以使用邊緣計算,通過把計算動態(tài)資源的代碼和數(shù)據也放在 CDN 的節(jié)點上,這樣就可以在 CDN 里獲取動態(tài)資源不用回源了。



























