直擊阿里雙11神秘技術:PB級大規模文件分發系統「蜻蜓」
導讀:2017天貓雙11, 交易峰值32.5萬/秒,支付峰值25.6萬/秒,資料庫處理峰值4200萬次/秒,成交額1682億數字的背後是50+神秘技術!其中,阿里集團基礎設施蜻蜓,在雙11期間,對上萬台伺服器同時下發5GB的數據文件,讓大規模文件分發靠蜻蜓系統完美實現。
蜻蜓,通過解決大規模文件下載以及跨網路隔離等場景下各種難題,大幅提高數據預熱、大規模容器鏡像分發等業務能力。月均分發次數突破20億次,分發數據量3.4PB。其中容器鏡像分發比natvie方式提速可高達57倍,registry網路出口流量降低99.5%以上。今天,阿里巴巴集團基礎架構事業群運維中台負責人,親歷者如柏,將為我們詳述蜻蜓從文件分發到鏡像傳輸的技術之路。
蜻蜓的誕生
蜻蜓是阿里自研的P2P文件分發系統,是阿里基礎運維平台重要組成部分,是雲效-智能運維平台的核心競爭力,也是阿里雲容器服務的關鍵組件。
隨著阿里業務爆炸式增長,2015年時發布系統日均的發布量突破兩萬,很多應用的規模開始破萬,發布失敗率開始增高, 而根本原因就是發布過程需要大量的文件拉取,文件伺服器扛不住大量的請求,當然很容易想到伺服器擴容,可是擴容後又發現後端存儲成為瓶頸。此外,大量來自不同IDC的客戶端請求消耗了巨大的網路帶寬,造成網路擁堵。
同時,很多業務走向國際化,大量的應用部署在海外,海外伺服器下載要回源國內,浪費了大量的國際帶寬,而且還很慢;如果傳輸大文件,網路環境差,失敗的話又得重來一遍,效率極低。
於是很自然的就想到了P2P技術,因為P2P技術並不新鮮,當時也調研了很多國內外的系統,但是調研的結論是這些系統的規模和穩定性都無法達到我們的期望。所以就有了蜻蜓這個產品。
設計目標
針對這些痛點,蜻蜓在設計之初定了幾個目標:
1. 解決文件源被打爆的問題,在Host之間組P2P網,緩解文件伺服器壓力,節約跨IDC之間的網路帶寬資源。
2. 加速文件分發速度,並且保證上萬伺服器同時下載,跟一台伺服器下載沒有太大的波動。
3. 解決跨國下載加速和帶寬節約。
4. 解決大文件下載問題,同時必須要支持斷點續傳。
5. Host上的磁碟IO,網路IO必須可以被控制,以避免對業務造成影響。
系統架構
蜻蜓整體架構分三層:第一層是Config Service, 他管理所有的Cluster Manager,Cluster Manager又管理所有的Host, Host就是終端,dfget就是類似wget的一個客戶端程序。
Config Service 主要負責Cluster Manager的管理、客戶端節點路由、系統配置管理以及預熱服務等等。簡單的說, 就是負責告訴Host,離他最近的一組Cluster Manager的地址列表,並定期維護和更新這份列表,使Host總能找到離他最近的Cluster Manager。
Cluster Manager 主要的職責有兩個:
1. 以被動CDN方式從文件源下載文件並生成一組種子分塊數據;
2. 構造P2P網路並調度每個peer之間互傳指定的分塊數據。
Host上就存放著dfget,dfget的語法跟wget非常類似。主要功能包括文件下載和P2P共享等。
在阿里內部我們可以用StarAgent來下發dfget指令,讓一組機器同時下載文件,在某種場景下一組機器可能就是阿里所有的伺服器,所以使用起來非常高效。除了客戶端外, 蜻蜓還有Java SDK,可以讓你將文件「PUSH」到一組伺服器上。
下面這個圖闡述了兩個終端同時調用dfget,下載同一個文件時系統的交互示意圖:
兩個Host和CM會組成一個P2P網路,首先CM會查看本地是否有緩存,如果沒有,就會回源下載,文件當然會被分片,CM會多線程下載這些分片,同時會將下載的分片提供給Host們下載,Host下載完一個分片後,同時會提供出來給peer下載,如此類推,直到所有的Host全部下載完。
本地下載的時候會將下載分片的情況記錄在metadata里,如果突然中斷了下載,再次執行dfget命令,會斷點續傳。
下載結束後,還會比對MD5,以確保下載的文件和源文件是完全一致的。蜻蜓通過HTTP cache協議來控制CM端對文件的緩存時長,CM端當然也有自己定期清理磁碟的能力,確保有足夠的空間支撐長久的服務。
在阿里還有很多文件預熱的場景,需要提前把文件推送到CM端,包括容器鏡像、索引文件、業務優化的cache文件等等。
在第一版上線後,我們進行了一輪測試, 結果如下圖:
X軸是客戶端數量, Y軸是下載時長,
文件源:測試目標文件200MB(網卡:千兆bit/s)
Host端:百兆bit/s網卡
CM端:2台伺服器(24核 64G,網卡:千兆bit/s)
從這個圖可以看出兩個問題:
1. 傳統模式隨著客戶端的增加,下載時長跟著增加,而dfget可以支撐到7000客戶端依然沒變好。
2. 傳統模式到了1200客戶端以後就沒有數據了,因為數據源被打爆了。
每年雙11之前都是發布高峰期, 2015年雙11就是靠蜻蜓完美渡過了。
從發布系統走向基礎設施
2015年雙11後,蜻蜓的下載次數就達到了12萬/月,分發量4TB。當時在阿里還有別的下載工具,如wget,curl,scp,ftp 等等,也有自建的小規模文件分發系統。我們除了全面覆蓋自身發布系統外,也做了小規模的推廣。到2016年雙11左右,我們的下載量就達到了1.4億/月,分發量708TB,業務增長了近千倍。
2016年雙11後我們提出了一個更高的目標, 希望阿里大規模文件分發和大文件分發90%的業務由蜻蜓來承擔。我們希望蜻蜓成為全集團的基礎設施。
我希望通過這個目標錘鍊出最好的P2P文件分發系統。此外也可以統一集團內所有的文件分發系統。統一可以讓更多的用戶受益,但統一從來不是終極目標, 統一的目的是:1. 減少重複建設;2. 全局優化。
只要優化蜻蜓一個系統,全集團都能受益。比如我們發現系統文件是每天全網分發的,而光這一個文件壓縮的話就能給公司每天節省9TB網路流量。跨國帶寬資源尤其寶貴。而如果大家各用各的分發系統,類似這樣的全局優化就無從談起。
所以統一勢在必行!
在大量數據分析基礎上,我們得出全集團文件分發的量大概是3.5億次/周,而我們當時的佔比只有10%不到。
經過半年努力,在2017年4月份,我們終於實現了這個目標, 達到90%+的業務佔有率,業務量增長到3億次/周(跟我們之前分析的數據基本吻合),分發量977TB,這個數字比半年前一個月的量還大。
當然,不得不說這跟阿里容器化也是密不可分的,鏡像分發流量大約佔了一半。下面我們就來介紹下蜻蜓是如何支持鏡像分發的。在說鏡像分發之前先說下阿里的容器技術。
阿里的容器技術
容器技術的優點自然不需要多介紹了,全球來看,容器技術以Docker為主佔了大部分市場,當然還有其他解決方案:比如rkt,Mesos Uni Container,LXC等,而阿里的容器技術命名為Pouch。早在2011年,阿里就自主研發了基於LXC的容器技術T4,只是當時我們沒有創造鏡像這個概念,T4還是當做虛擬機來用,當然比虛擬機要輕量的多。
2016年阿里在T4基礎上做了重大升級,演變為今天的Pouch,並且已經開源。目前Pouch容器技術已經覆蓋阿里巴巴集團幾乎所有的事業部,在線業務100%容器化,規模高達數十萬。鏡像技術的價值擴大了容器技術的應用邊界,而在阿里如此龐大的應用場景下,如何實現高效「鏡像分發」成為一個重大命題。
回到鏡像層面。宏觀上,阿里巴巴有規模龐大的容器應用場景;微觀上,每個應用鏡像在鏡像化時,質量也存在參差不齊的情況。
理論上講用鏡像或者用傳統「基線」模式,在應用大小上不應該有非常大的區別。但事實上這完全取決於Dockerfile寫的好壞,也取決於鏡像分層是否合理。阿里內部其實有最佳實踐,但是每個團隊理解接受程度不同,肯定會有用的好壞的之分。尤其在一開始,大家打出來的鏡像有3~4GB這都是非常常見的。
所以作為P2P文件分發系統,蜻蜓就有了用武之地,無論是多大的鏡像,無論是分發到多少機器,即使你的鏡像打的非常糟糕,我們都提供非常高效的分發,都不會成瓶頸。這樣就給我們快速推廣容器技術,讓大家接受容器運維模式,給予了充分消化的時間。
容器鏡像
在講鏡像分發之前先簡單介紹下容器鏡像。我們看下Ubuntu系統的鏡像:我們可以通過命令 docker history ubuntu:14.04 查看 ubuntu:14.04,結果如下:
需要注意的是:鏡像層 d2a0ecffe6fa 中沒有任何內容,也就是所謂的空鏡像。
鏡像是分層的,每層都有自己的ID和尺寸,這裡有4個Layer,最終這個鏡像是由這些Layer組成。
Docker鏡像是通過Dockerfile來構建,看一個簡單的Dockerfile:
鏡像構建過程如下圖所示:
可以看到,新鏡像是從 base 鏡像一層一層疊加生成的。每安裝一個軟體,就在現有鏡像的基礎上增加一層。
當容器啟動時,一個可寫層會被載入到鏡像的頂層,這個可讀可寫層也被稱為「容器層」,容器層之下都是「鏡像層」,都是只讀的。
如果鏡像層內容為空,相應的信息會在鏡像json文件中描述,如果鏡像層內容不為空,則會以文件的形式存儲在OSS中。
鏡像分發
以阿里雲容器服務為例,傳統的鏡像傳輸如上圖所示,當然這是最簡化的一種架構模式,實際的部署情況會複雜的多,還會考慮鑒權、安全、高可用等等。
從上圖可以看出,鏡像傳輸跟文件分發有類似的問題,當有一萬個Host同時向Registry請求時,Registry就會成為瓶頸,還有海外的Host訪問國內Registry時候也會存在帶寬浪費、延時變長、成功率下降等問題。
下面介紹下Docker Pull的執行過程:
Docker Daemon調用Registry API得到鏡像的Manifest,從Manifest中能算出每層的URL,Daemon隨後把所有鏡像層從Registry並行下載到Host本地倉庫。
所以最終,鏡像傳輸的問題變成了各鏡像層文件的並行下載的問題。而蜻蜓擅長的正是將每層鏡像文件從Registry用P2P模式傳輸到本地倉庫中。
那麼具體又是如何做到的呢?
事實上我們會在Host上啟動dfGet proxy,Docker/Pouch Engine的所有命令請求都會通過這個proxy,我們看下圖:
首先,docker pull命令,會被dfget proxy截獲。然後,由dfget proxy向CM發送調度請求,CM在收到請求後會檢查對應的下載文件是否已經被緩存到本地,如果沒有被緩存,則會從Registry中下載對應的文件,並生成種子分塊數據(種子分塊數據一旦生成就可以立即被使用);如果已經被緩存,則直接生成分塊任務,請求者解析相應的分塊任務,並從其他peer或者supernode中下載分塊數據,當某個Layer的所有分塊下載完成後,一個Layer也就下載完畢了,同樣,當所有的Layer下載完成後,整個鏡像也就下載完成了。
蜻蜓支持容器鏡像分發,也有幾個設計目標:
1. 大規模並發:必須能支持十萬級規模同時Pull鏡像。
2. 不侵入容器技術內核(Docker Daemon, Registry):也就是說不能改動容器服務任何代碼。
3. 支持Docker,Pouch,Rocket ,Hyper等所有容器/虛擬機技術。
4. 支持鏡像預熱:構建時就推送到蜻蜓集群CM。
5. 支持大鏡像文件:至少30GB。
6. 安全。
Native Docker V.S 蜻蜓
我們一共做了兩組實驗:
實驗一:1個客戶端
1. 測試鏡像大小:50MB、200MB、500MB、1GB、5GB
2. 鏡像倉庫帶寬:15Gbps
3. 客戶端帶寬:雙百兆bit/s網路環境
4. 測試規模:單次下載
Native和蜻蜓(關閉智能壓縮特性)平均耗時基本接近,蜻蜓稍高一點,因為蜻蜓在下載過程中會校驗每個分塊數據的MD5值,同時在下載之後還會校驗整個文件的MD5,以保證下載的文件跟源文件是一致的;而開啟了智能壓縮的模式下,其耗時比Native模式還低!
實驗二:多客戶端並發
1. 測試鏡像大小:50MB、200MB、500MB、1GB、5GB
2. 鏡像倉庫帶寬:15Gbps
3. 客戶端帶寬:雙百兆bit/s網路環境
4. 多並發:10並發、200並發、1000並發
上圖可以看出,隨著下載規模的擴大,蜻蜓與Native模式耗時差異顯著擴大,最高可提速可以達20倍。在測試環境中源的帶寬也至關重要,如果源的帶寬是2Gbps,提速可達57倍。
下圖是下載文件的總流量(並發數 * 文件大小)和回源流量(去Registry下載的流量)的一個對比:
向200個節點分發500M的鏡像,比docker原生模式使用更低的網路流量,實驗數據表明採用蜻蜓後,Registry的出流量降低了99.5%以上;而在1000並發規模下,Registry的出流量更可以降低到99.9%左右。
阿里巴巴實踐效果
蜻蜓在阿里投入使用大概已有兩年,兩年來業務發展迅速,從分發的次數來統計目前一個月接近20億次,分發3.4PB數據。其中容器鏡像的分發量接近一半。
在阿里最大的一次分發應該就是今年雙11期間, 要對上萬台伺服器同時下發5GB的數據文件。
走向智能化
阿里在AIOps起步雖然不是最早, 但是我們近年來投入巨大,並在很多產品上有所應用。蜻蜓這個產品中有以下應用:
智能流控
流控在道路交通中很常見,比如中國道路限速規定,沒有中心線的公路,限速為40公里/小時;同方向只有1條機動車道的公路,限速為70公里/小時;快速道路80公里;高速公路最高限速為120公里/小時等等。這種限速對每輛車都一樣,顯然不夠靈活,所以在道路非常空閑的情況下,道路資源其實是非常浪費的,整體效率非常低下。
紅綠燈其實也是流控的手段,現在的紅綠燈都是固定時間,不會根據現實的流量來做智能的判斷,所以去年10月召開的雲棲大會上,王堅博士曾感慨,世界上最遙遠的距離不是從南極到北極,而是從紅綠燈到交通攝像頭,它們在同一根桿上,但從來沒有通過數據被連接過,攝像頭看到的東西永遠不會變成紅綠燈的行動。這既浪費了城市的數據資源,也加大了城市運營發展的成本。
蜻蜓其中一個參數就是控制磁碟和網路帶寬利用率的,用戶可以通過參數設定使用多少網路IO/磁碟IO。如上所述,這種方法是非常僵化的。所以目前我們智能化方面的主要思想之一是希望類似的參數不要再人為來設定,而是根據業務的情況結合系統運行的情況,智能的決定這些參數的配置。最開始可能不是最優解,但是經過一段時間運行和訓練後自動達到最優化的狀態,保證業務穩定運行同時又儘可能的充分利用網路和磁碟帶寬,避免資源浪費。
智能調度
分塊任務調度是決定整個文件分發效率高低與否的關鍵因素,如果只是通過簡單的調度策略,比如隨機調度或者其他固定優先順序的調度,這種做法往往會引起下載速率的頻繁抖動,很容易導致下載毛刺過多,同時整體下載效率也會很差。為了最優化任務調度,我們經歷了無數次的嘗試和探索,最終通過多維度(比如機器硬體配置、地理位置、網路環境、歷史下載結果和速率等等維度的數據)的數據分析(主要利用了梯度下降演算法,後續還會嘗試其他演算法),智能動態決定當前請求者最優的後續分塊任務列表。
智能壓縮
智能壓縮會對文件中最值得壓縮的部分實施相應的壓縮策略,從而可以節約大量的網路帶寬資源。
對容器鏡像目前的實際平均數據來看,壓縮率(Compression Ration) 是40%,也就是說100MB鏡像可以壓縮到40MB。針對1000並發規模,通過智能壓縮可以減少60%的流量。
安全
在下載某些敏感的文件(比如秘鑰文件或者賬號數據文件等)時,傳輸的安全性必須要得到有效的保證,在這方面,蜻蜓主要做了兩個工作:
1. 支持攜帶HTTP的header數據,以滿足那些需要通過header來進行許可權驗證的文件源;
2. 利用對稱加密演算法,對文件內容進行傳輸加密。
開源
隨著容器技術的流行,容器鏡像這類大文件分發成為一個重要問題,為了更好的支持容器技術的發展,數據中心大規模文件的分發,阿里決定開源蜻蜓來更好的推進技術的發展。阿里將持續支持開源社區,並把自己經過實戰檢驗的技術貢獻給社區。敬請期待。
商業化
蜻蜓除了用於阿里集團內部容器化,也完全兼容社區版Docker,可以和阿里雲容器服務(https://www.aliyun.com/product/containerservice)和飛天專有雲敏捷版(https://yq.aliyun.com/articles/224507)無縫結合在一起,在公共雲和專有雲環境下支撐大規模的容器鏡像分發。
總結
蜻蜓通過使用P2P技術同時結合智能壓縮、智能流控等多種創新技術,解決大規模文件下載以及跨網路隔離等場景下各種文件分發難題,大幅提高數據預熱、大規模容器鏡像分發等業務能力。
蜻蜓支持多種容器技術,對容器本身無需做任何改造,鏡像分發比natvie方式提速可高達57倍,Registry網路出流量降低99.5%以上。承載著PB級的流量的蜻蜓,在阿里已然成為重要的基礎設施之一,為業務的極速擴張和雙11大促保駕護航。
Reference
[1]Docker Overview:
https://docs.docker.com/engine/docker-overview/
[2]Where are docker images stored:
http://blog.thoward37.me/articles/where-are-docker-images-stored/
[3]Image Spec:
https://github.com/moby/moby/blob/master/image/spec/v1.md
[4]Pouch開源地址:
https://github.com/alibaba/pouch
[5]蜻蜓開源地址:
https://github.com/alibaba/dragonfly
[6]阿里雲容器服務:
http://click.aliyun.com/m/27426/
[7]飛天專有雲敏捷版:
https://yq.aliyun.com/articles/224507
[8]雲效智能運維平台:
https://www.aliyun.com/product/yunxiao
本文作者:毛茂德(花名:如柏):阿里巴巴集團基礎架構事業群運維中台負責人,親歷者。主導架構設計高可靠、高並發、大規模的基礎運維平台和應用運維平台, 十餘年來堅持不懈的追求研發、測試、運維效率提升,推動DevOps實施落地。目前正致力於打造基於混合雲的應用運維無人值守解決方案以及自動化、數據化、智能化應用運維解決方案。曾任職於IONA,RedHat,eBay,也是 Apache 頂級項目CXF 初創成員之一。
PS:致力於打造具備世界級影響力的雲效智能運維平台,誠聘資深技術/產品專家
工作地點:杭州、北京、美國
點擊招聘
蜻蜓即將輸出到阿里雲,服務於更多企業,也將成為阿里云云效一站式協同研發雲重要的功能。
原文鏈接
更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎
推薦閱讀:
※iOS 客戶端 HTTPS 防中間人攻擊實踐
※Let's Encrypt 使用教程,免費的SSL證書,讓你的網站擁抱 HTTPS
※理解HTTPS
※為什麼要把網站升級到HTTPS