CDN系統總結筆記


https://blog.goquxiao.com/posts/2016/01/01/cdn-note/

2015年,也花了半年左右的時間用於研究、開發、維護公司的靜態CDN系統了,自己也從對CDN系統一無所知、客戶帶寬只有幾MB的規模,到最終全國客戶帶寬到了幾十GB的規模。回顧整個過程,真算是對自己的生理、心理的一種考驗,驚險、刺激!同時,也是對自己的一種鍛煉。趁着元旦假期,從原理、架構、業務等方面,試着粗淺的總結下CDN系統。

原理

CDN的全稱是『Content Delivery Network』,內容分發網絡,主要的目的就是提高全國以及全球各地用戶訪問資源的速度,從而提升各項互聯網產品的用戶體驗。我們可以設想一下,一個互聯網產品,肯定會通過各種資源的形式提供服務,這些資源包括:圖片、視頻、還有普通用戶感知不到的js/css腳本,而這些資源又是存儲在服務器上,通過網絡提供給用戶。如果沒有CDN的話,用戶的每一個請求都會請求至你的服務器(CDN系統中叫做源站),收到服務器的處理能力以及網絡情況的影響,等到請求到達一定規模之后,必然會出現請求響應過慢、甚至無法服務的情況。如果需要解決的話,就要自行部署冗余的在各運營商機房部署服務器、購買網絡帶寬,成本必然升高不少,同時還需要自己處理各個機房的各種問題,人力和精力還會投入不少。但是,有了CDN的話,就可以將服務器的各項資源分發至CDN的各個節點,通過流量調度,用戶的請求就會打到鏈路最優的CDN節點上面,讓資源的響應達到最快,增加的費用只是向CDN廠商支付的帶寬費用。

從技術角度上,(靜態資源)CDN就是基於HTML協議中的緩存機制,將客戶的數據存儲在離客戶『最近』的節點,以達到加速功能的。這篇《 Caching Tutorial 》講解的比較清楚,當然你也可以看權威的HTML的RFC。CDN節點就是位於用戶和源站之間,作為一個中間的緩存代理。用戶(的瀏覽器)發起了資源的請求,並沒有之前請求至源站,而是請求到了CDN節點,如果CDN節點認為該資源是沒有過期的,就直接將資源數據返回至用戶;如果該資源是過期的,CDN節點則會發送請求至源站,拿到源站的數據之后,一方面再返回給用戶,另一方面自己將數據存儲起來,用於用戶的后續相同請求。

架構

架構方面,一個CDN系統由以下幾個子系統組成:

  • 緩存系統
  • 流量調度系統
  • 業務系統
  • 數據報表系統

架構圖如下:

緩存系統

緩存系統,是CDN系統提供核心功能的模塊,也是直接與用戶打交道的模塊。他的功能比較單純:

  • 接收用戶的HTTP請求,返回緩存資源
  • 維護用戶的資源緩存,存儲在內存和磁盤
  • 向客戶源站或者更高層緩存系統發送請求,獲取原始數據

開源的緩存系統也有不少,例如Squid、Apache Traffic Server、Varnish,甚至Nginx、HAProxy,也可以通過開發Module的形式成為一個緩存服務器。《 服務好“最后一公里”,高效CDN架構經驗 》這篇文章通過多個緯度對比了這些開源緩存系統,概括的還算不錯。根據之前的調研,CDN廠商使用的較多的是Squid和ATS,大部分也會在這些開源緩存系統上面進行二次開發。

在部署方面,一般采用二級緩存方式,這兩級緩存節點,一級叫做『邊緣節點』,另一級叫做『中心節點』。用戶發起了一個資源請求,首先是請求到了邊緣節點,如果邊緣節點就有未過期的緩存,就直接返回給用戶;如果沒有的話,邊緣節點就會請求中心節點,再以此類推;最后,如果連中心節點也沒有緩存,就會請求客戶的源站,最終將數據返回給用戶。邊緣節點的分布應該是盡量做到全面分散分布,需要選擇各大小運營商的鏈路,為了能覆蓋到盡可能多的用戶;中心節點則是數量相對較少的各運營商訪問鏈路質量好、本身容災度高的IDC,這樣可以做到對於源站的高效回源訪問,中心節點一般選擇多線BGP網絡。

流量調度系統(GSLB)

剛才說了,用戶請求上了CDN的資源,首先會指向一個邊緣節點,那究竟選擇哪一個邊緣節點呢?這就需要流量調度系統(Global Server Load Balance,簡稱GSLB)了。GSLB實現了在互聯網上不同地域的服務器間的流量調配,保證使用最佳的服務器服務離自己最近的客戶,從而確保訪問質量。

GSLB系統分為三大部分:采集/計算、調度、DNS系統。

簡單的說,可以理解為下面三個步驟:

  1. 通過監控得到的節點鏈路質量數據、以及用戶訪問情況
  2. 將監控數據作為輸入,通過調度算法,得出CDN節點 X 用戶(地域+運營商)的質量分數矩陣
  3. 將質量分數矩陣轉換為域名解析系統的配置,重新加載配置

這三個步驟就會形成了一次迭代過程,GSLB系統就通過不斷的迭代不斷的優化流量的調度。不過,在不同維度上面進行考量,迭代的周期也是不一樣的。如果是考慮服務的可用性,采集/計算是需要實時、不間斷進行的,因此迭代的周期也會較短,在秒級別或者分鍾級別;如果是在可用性基本一致的情況下,選擇鏈路最好的節點(用戶<->邊緣、邊緣<->上層),則可以使用較長周期的觀測數據,例如小時級別或者天級別,用以考量某個鏈路的網絡穩定性(因為有時穩定性要比帶寬、性能要重要,而穩定性又需要較長時間才能判斷出來),然后再進行流量的調整。

除了通過算法進行自動調度,GSLB同樣需要支持手動的配置,這同樣是由於業務需求,例如需要中國用戶訪問位於中國的源站、歐洲用戶訪問位於美國的源站(雖然可能歐洲用戶到中國的鏈路更好)。

具體三大部分的介紹,可以再看下我之前寫的兩篇文章: [GSLB調研一] 和 [GSLB調研二]

業務系統

有了緩存系統和流量調度系統,理論上整個用戶經由GSLB決定CDN節點、CDN節點再去刷新資源進行緩存並返回給用戶的流程就已經跑通了。不過,還是需要有一個業務系統,能夠用戶或者管理員能否方便的對CDN的配置、緩存等進行操作。

業務系統按照這些功能可以分為兩個子系統:

  • 域名管理系統
  • 緩存管理系統

域名管理系統

域名管理,就是當接入CDN客戶時,需要將客戶的需求,變為緩存系統的配置,比如Squid中的 ACL 、 refresh_pattern 等。一般來說,CDN廠商要求客戶提供以下信息:

  • 域名相關
    • 緩存的URL列表
    • 源站IP或者域名
    • 日常帶寬數據
  • 源服務器信息
    • 源服務器數量、所處運營商
    • 提供服務的端口
  • 安全相關
    • 是否有防火牆(如果有,需要添加CDN的IP至白名單)
    • 源服務器的最大連接數
    • Referer限制
    • UA限制
  • 緩存策略
    • 緩存資源的類型

    • 過期策略
      • 通過cache-control:max-age
      • 通過Expires
  • 資源相關
    • 單個最大資源大小
    • 平均大小
    • 緩存資源整體大小

另外,有時客戶也會有一些特殊的需求。比如我們之前遇到的:

客戶有i0.a.com/1.jpg、 i1.a.com/1.jpg 兩個需要緩存的URL,但是在CDN系統中只需要當做一份數據來存儲。

或者,客戶的URL都會有用時間戳當做請求參數,例如 a.com/1.jpg?t=1435432196,需要CDN把不同時間戳的資源都當做一份數據來存儲。

其它方面,不同的CDN服務商也會提供更細化的功能,例如又拍雲的回源策略,就做得很細致:

緩存操作系統

客戶將域名上線至CDN系統之后,雖然本身可以依靠資源上的Cache-control或者Expires進行緩存過期自動獲取最新資源,但是出於一些業務需求(時效性較強的活動頁面、上線新版式、線上bug處理等),仍然需要人工進行統一對CDN上的資源進行操作。

操作的方式一般來說,分為『刷新』和『預取』。

『刷新』就是指直接將CDN上的指定資源的狀態設置為過期,這樣當有用戶請求該資源的時候,CDN節點就會去源站或者上一層CDN獲取最新的資源。刷新操作,又可以分為URL刷新和目錄刷新。URL刷新就是用戶直接提交需要刷新的URL,緩存操作系統去刷新這個URL;目錄刷新要稍微復雜一些,用戶提交的是一個URL前綴,緩存操作系統需要將所有包含這個前綴的所有URL都進行刷新。

對於原生的緩存系統來說,緩存的存儲形式都是 key-value ,沒有一種我們直觀感受到的URL路徑的樹形結構,因此並不直接支持刷新目錄的功能,需要對原有系統進行二次開發。

一種比較簡單的做法是:通過CDN緩存系統的訪問日志,分析出 目錄 -> URL列表 的對應關系,保存在專門的刷新系統。當用戶請求目錄刷新時,刷新系統就可以將對應的URL走原有的URL刷新流程,完成目錄刷新,這是我們目前的解決方案。這種方案的特點是:實現比較簡單,但是能夠刷新的URL都得是用戶訪問過的才行,另外統計出 目錄 -> URL列表 會有一定的延時。

另外一種做法是通過修改CDN緩存系統,在其中增加數據結構來之后次目錄刷新。比較詳細的介紹目錄刷新機制的是阿里CDN的技術分享《 阿里雲CDN高性能Cache系統架構之道 》,主要思想是將需要刷新的目錄通過Hash表以及字典樹(Tire)進行保存,當有用戶請求時,就可以判斷出該URL是否符合某一個刷新目錄,對比兩者的時間戳,再決定是否將該資源進行回源。原理圖如下:

這種做法的主要特點是技術門檻比較高,平均性能較高,但是每次用戶請求都需要判斷是否命中了目錄刷新,將性能的損失分攤到了每次請求。

『預取』則是在刷新的基礎上,當資源已經判斷過期的情況下,再去自動獲取一次最新資源存儲至CDN節點,這樣的好處就是用戶訪問資源的時候,不會出現CDN回源的情況,減少用戶這次訪問的響應時間。

PS:在接客戶的時候,的確會碰到個別2B客戶提出一些奇葩需求,例如說要緩存html文件,或者請求參數本來可以當做版本號讓CDN自動抓取新資源,客戶仍要求緩存不帶請求參數的URL,然后自己手動刷新緩存…… 畢竟本身客戶的水平就是參差不齊,另外CDN市場的客戶也是需要服務提供商來教育的。

數據報表系統

客戶已經將業務接入到CDN了,一方面需要讓客戶能夠查看到接入站點的運行情況,另一方面服務商也需要根據數據向客戶收費,因此還需要一個數據報表系統。

因為原始數據以及統計的數據量都比較大,另外也需要一定的實時性(最多不能超過5分鍾),並且由於CDN業務的特性,節點是分布在各個地域和運營商的,所以整個數據報表系統也是有一定的技術難度的。數據處理的流程包括了:

  • 數據本地采集
  • 數據上報
  • 數據落地(持久化)
  • 數據解析、清洗、格式化
  • 數據預處理
  • 數據實時統計、歷史統計
  • 數據展現

數據內容方面,一般則至少包括:

  • 流量
  • 帶寬(最細粒度時間區間內的最大流量)
  • HTTP返回碼統計
  • 緩存Hit數/Miss數(用於計算不同時間區間的命中率/回源率)
  • 服務器地域信息

有了這些數據,就能夠向客戶展現比較豐富的圖表了。此外,如果數據粒度可以細化到原來數據(訪問日志)的話,那還可以提供更高級的功能,例如:日志分析/下載、全國用戶來源統計等等。

以下是我們報表系統的部分截圖:

流量帶寬

訪問量/回源率

HTTP返回碼統計


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM