到現在為止,我們基本上已經了解了網絡協定中的大部分常用協定,對于整個 HTTP 請求流程也較為熟悉了。從無到有後,我們就要考慮如何優化“有”這個過程,也就是我們常見的請求優化。而現在的技術棧中,CDN 是最常用的一種方式。
在了解 CDN 前,我們可以先了解下現代社會的物流配置。
例如我們去電商網站下單買東西,這個東西一定要從電商總部的中心倉庫送過來嗎?在電商剛興起的時候,所有的配送都是從中心倉庫發貨,是以買家可能要很久才能收到貨。但是後來電商網站的物流系統學聰明了,他們在全國各地建立了很多倉庫,而不是隻有總部的中心倉庫才可以發貨。
電商網站根據統計大概知道,北京、上海、廣州、深圳、杭州等地,每天能夠賣出去多少書籍、紙巾、包、電器等存放期較長的商品,就将這些商品分布存放在各地倉庫中,客戶一下單,就從臨近的倉庫發貨,大大減少了運輸時間,提高了使用者體驗。
同樣的,網際網路也借鑒了“就近配送”這個思路。
CDN 就近配送
全球有那麼多的資料中心,無論在哪裡上網,臨近不遠的地方基本上都有資料中心。可以在每個資料中心裡部署幾台機器,形成一個緩存叢集來緩存部分熱資料,這樣使用者通路資料的是,就可以就近通路了。
這些分布在各個地方的各個資料中心的節點,我們一般稱為邊緣節點。
由于邊緣節點數目比較多,但是每個叢集規模比較小,不可能緩存下來所有東西,因而可能無法命中,這樣就會在邊緣節點之上,形成了區域節點。
區域節點規模較大,緩存的資料也較多,命中的機率也就更大。而在區域節點之上是中心節點,規模更大,緩存資料更多。
就這樣,在這樣一層層的節點中緩存資料,提高響應速度。但是所有的節點都沒有緩存資料,就隻有進行回源網站通路了。
如上圖,就是 CDN 的分發系統的架構。CDN 系統的緩存,是一層層的,能不通路源資料,就不通路。這也是電商網站物流系統的思路,廣州找不到,找華南局,華南局找不到,再找南方局。
有了這個分發系統之後,用戶端如何找到相應的邊緣節點進行通路呢?
還記得咱們之前了解的基于 DNS 的全局負載均衡嗎?這個負載均衡主要用來選擇一個就近的相同營運商的伺服器進行通路。
同樣的,CDN 分發網絡也可以用相同的思路選擇最合适的邊緣節點。
如上圖,CDN 的負載均衡流程圖。
1)沒有 CDN 的情況(圖中虛線部分)。使用者向浏覽器輸入 www.web.com 這個域名,用戶端通路本地 DNS 伺服器的時候,如果本地 DNS 伺服器有緩存,則傳回網站的位址。如果沒有,遞歸查詢到網站的權威 DNS 伺服器,這個權威 DNS 伺服器是負責 web.com 的,它會傳回網站的 IP 位址。本地 DNS 伺服器緩存下 IP 位址,将 IP 位址傳回,然後用戶端直接通路這個 IP 位址,就通路到了網站。
2)有 CDN 的情況(圖中實線部分)。此時,在 web.com 這個權威 DNS 伺服器上,會設定一個 CNAME 别名,指向另外一個域名 www.web.cdn.com,傳回給本地 DNS 伺服器。
當本地 DNS 伺服器拿到這個新的域名時,需要繼續解析這個新的域名。這個時候,再通路的就不是 web.com 這個權威 DNS 伺服器了,而是 web.cdn.com 的權威 DNS 伺服器,這是 CDN 自己的權威 DNS 伺服器,在這個伺服器上,還是會設定一個 CNAME,指向另外一個域名,也就是 CDN 網絡的全局負載均衡器。
接下來,本地 DNS 伺服器去請求 CDN 的全局負載均衡器解析域名。全局負載均衡器會為使用者選擇一台合适的緩存伺服器提供服務,選擇的依據包括:
- 根據使用者 IP 位址,判斷哪一台伺服器距使用者最近;
- 使用者所處的營運商;
- 根據使用者所請求的 URL 中攜帶的内容名詞,判斷哪一台伺服器上有使用者所需的内容;
- 查詢各個伺服器目前的負載情況,判斷哪一台伺服器尚有服務能力。
基于以上這些條件,進行綜合分析之後,全局負載均衡器會傳回一台緩存伺服器的 IP 位址。
本地 DNS 伺服器緩存這個 IP 位址,然後将 IP 傳回給用戶端,用戶端去通路這個邊緣節點,下載下傳資源。
緩存伺服器響應使用者請求,将使用者所需内容傳送給使用者。如果這台緩存伺服器上沒有使用者想要的内容,那麼這台伺服器就要向它的上一級緩存伺服器請求内容,直至追溯到網站的源伺服器,将内容拉到本地。
CDN 緩存内容
保存期限長的日用品因為不容易過期,是以比較容易緩存。同樣的,網際網路中的靜态頁面、圖檔等,幾乎不怎麼改變,是以也适合緩存。而像生鮮之類的儲存時間較短的,對應網際網路中的動态資源,就需要用到動态 CDN 。
靜态資源緩存
還記得上圖這個接入層緩存的架構嗎?在進入資料中心的時候,我們希望通過最外層接入層的緩存,将大部分靜态資源的通路攔在邊緣。而 CDN 則更進一步,将這些靜态資源緩存到離使用者更近的資料中心外。總體來說,就是縮短使用者的“通路距離”。離客戶越近,客戶通路性能越好,時延越低。
流媒體 CDN
在靜态内容中,流媒體也大量使用了 CDN。
CDN 支援流媒體協定。例如前面講過的 RTMP 協定。在很多情況下,這相當于一個代理,從上一級緩存讀取内容,轉發給使用者。由于流媒體往往是連續的,因而可以進行預先緩存的政策,也可以預先推送到使用者的用戶端。
對于靜态頁面來講,内容的分發往往采取拉取的方式。也即,當發現緩存未命中的是,再去上一級進行拉取。
這個方式對于流媒體就不合适了。流媒體資料量大,如果出現回源,壓力會比較大,是以往往采取主動推送的模式,将熱點資料主動推送到邊緣節點。
對于流媒體來講,很多 CDN 還提供預處理服務。也就是在檔案分發之前,進行一定的處理。例如将視訊轉換成不同的碼流,以适應不同的網絡帶寬的使用者需求。再如對視訊進行分片,降低存儲壓力,也使得用戶端可以選擇使用不同的碼率加載不同的分片。這就是我們常見的,超清、标清、流暢等。
除此之外,流媒體 CDN 還有個關鍵的防盜鍊問題。因為視訊要花大價錢買版權,如果流媒體被其他網站盜走,在其他網站的播放,那損失就大了。
對于防盜鍊問題,最常用也最簡單的方法就是利用 HTTP 頭的 refer 字段。當浏覽器發送請求的時候,一般會帶上 refer。告訴伺服器是從哪個頁面連結過來的,伺服器基于此可以獲得一些資訊用于處理。如果 refer 資訊不是來自本站,就阻止通路或者跳到其它連結。
refer 的機制相對比較容易破解,是以還需要其它的機制配合。
一種常用的機制是時間戳防盜鍊。使用 CDN 的管理者可以在配置界面上,和 CDN 廠商約定一個加密字元串。
用戶端通路時,取出目前的時間戳、要通路的資源極其路徑,聯通加密字元串進行前面算法得到一個字元串,然後生成一個下載下傳連結,帶上這個前面字元串和截止時間戳去通路 CDN。
在服務端,取出過期時間,和目前 CDN 節點時間進行比較,确認請求是否過期。然後 CDN 服務端根據請求的資源及路徑、時間戳、和約定的加密字元串進行簽名。隻有簽名和用戶端發送的一緻,才會将資源傳回給客戶。
動态資源緩存
對于動态資源,用到動态 CDN。動态 CDN 主要有兩種模式:
1)“生鮮超市模式”,也就是邊緣計算模式。
既然資料是動态生成的,是以資料的邏輯計算和存儲,也相應的放在邊緣的節點。其中定時從源資料那裡同步存儲的資料,然後在邊緣節點進行計算得到結果。
這種方式很像現在的生鮮超市。新鮮的海鮮大餐是動态的,很難事先做好緩存,因而将生鮮超市放在你家旁邊,既能夠送貨上門,也能夠現場烹饪。這就是邊緣計算的一種展現。
2)“冷鍊運輸模式”,也就是路徑優化模式。資料不是在邊緣計算生成的,而是在源站生成的,但是資料的下發則可以通過 CDN 的網絡,對路徑進行優化。
因為 CDN 節點較多,能夠找到離源站很近的邊緣節點,也能找到離使用者很近的邊緣節點。中間的鍊路完全由 CDN 來規劃,選擇一個更加可靠的路徑,使用類似專線的方式進行通路。
除此之外,這些資源進行傳輸的時候,由于 TCP 的流量控制和擁塞控制,可以在 CDN 加速網絡中調整 TCP 的參數,使得 TC 可以更加激進的傳輸資料。
所有這些手段就像冷鍊傳輸,優化整個物流運輸,全程冷凍高速運輸。不管是生鮮從你家旁邊超市送過去,還是從産地運送,保證到你家是新鮮的。
小結
- CDN 和電商系統的分布式倉儲系統一樣,分為中心節點、區域節點、邊緣節點,進而将資料緩存在離使用者最近的位置。
- CDN 最擅長的緩存是緩存靜态資料。除此之外還可以緩存流媒體資料。這時候要注意防盜鍊問題。它也支援動态資料的緩存,一種是邊緣計算,另一種是鍊路優化。
參考:
- What is a CDN?;
- 維基百科 - Content delivery network;
- 劉超 - 趣談網絡協定系列課;