新浪微博:大規模離線視頻處理系統的架構設計


微博視頻平臺在4億月活用戶吃瓜嗨聊的高併發、大流量背景下,既要保證用戶微博生產和消費體驗,又要支持業務快速迭代,確保正確性、穩定性和高可用性。本次演將以微博視頻大規模視頻離線處理系統的架構設計爲主題爲你們帶來大規模分佈式系統的架構設計,性能優化和高可用保障等一線實戰經驗。

文 / 霍東海
整理 / LiveVideoStack


你們好,我是來自新浪微博視頻平臺和微博平臺研發部的架構師霍東海,從2017年加入微博,目前在微博視頻平臺負責微博視頻離線處理系統架構等相關工做,包括大規模離線微服務系統的架構設計和服務保障體系的建設等。近期專一於視頻平臺技術體系的提高對用戶體驗提高的幫助,主導構建了微博SVE(Streaming Video Engine)系統,支持大併發場景下對視頻進行並行轉碼,大幅度提高轉碼效率。

1. 背景介紹



微博自己有大併發、大流量的特性,有4億+的月活,同時微博也是一個開放平臺,支持多種第三方分享,天天都會有百萬視頻分享需進行處理。


微博視頻業務大概分兩種業餘形態,一個如左圖所示,是豎版的短視頻分享,另外一個是如右圖所示的稍微長一點的橫向播放的短視頻。
微博視頻還有一些特殊的場景,例如在微博PC端點視頻按鈕會跳轉到酷燃網,它是一個5到15分鐘的短小綜藝類視頻分享的網站,如圖中,下面都是一些優酷,愛奇藝,騰訊等視頻網站分享到微博的視頻。
咱們微博視頻團隊面臨的業務場景是及其複雜的,咱們要在複雜的場景下解決視頻處理的問題。如圖中,咱們有微博視頻,酷燃視頻,付費視頻,微博故事,秒拍,以及經過開放平臺接入的視頻分享網站,微博在最上層會接入極其多的業務方。中間會引入業務調度中心,即業務調度層,對上層業務進行調度。


另外是數據同步,全部的視頻呈如今微博都是博文的形式,始終是須要和咱們本身的系統進行交互的。業務調度層的另一個做用就是對視頻內容進行分析。往下一層是文件存儲,媒體庫層。文件存儲包括文件上傳,文件存儲方面等的問題。媒體庫是視頻對象的源信息,如視頻分辨率URL,視頻長寬,用戶ID,博文內容等信息存儲。最下層是轉碼服務。咱們重點介紹的就是轉碼服務在微博場景下的思考。

2. 微博視頻轉碼服務架構與挑戰
2.1 視頻處理系統傳統架構



在講微博面臨的問題以前,先來了解一下視頻處理系統的傳統架構。例如,某一用戶在PC端或手機端有一個1080p,5Mbps的視頻須要上傳。在傳統的架構中,會先將文件傳到文件上傳服務,文件上傳服務將其傳到底層存儲。傳到存儲後,文件上傳服務會告知轉碼服務文件需進行轉碼。轉碼時轉碼服務經過調度器將轉碼任務傳到對應的轉碼集羣中的轉碼服務器。真正轉碼的機器,從存儲中下載用戶上傳的源文件,轉換成特定格式後回存到存儲中。
2.2 微博視頻轉碼服務 – 業務繁雜



對微博視頻而言,咱們有很是繁雜的業務,例如業務方會有不一樣的水印,一些用戶會對本身的視頻有特殊要求,另外系統要能知足線上驗證優化轉碼算法的需求,再加上轉碼服務自己會提供抽幀等基礎服務,要使這些融合在一塊兒快速方便的支持業務方的需求,咱們面臨很大的挑戰。
2.3 微博視頻轉碼服務 – 提速優化


另外,在優化視頻基礎體驗的時候,咱們會提出並行上傳來提升用戶上傳成功率,作相似斷點續傳的功能,咱們還會作並行轉碼完成雲廠商提出的分片轉碼。甚至咱們作到了用戶邊轉邊存,使視頻在用戶手機端完成分片,一邊分片一邊上傳,上傳的同時後臺進行轉碼,上傳完成的同時,轉碼便可完成,最後合併視頻完成發送。這極大的提升了用戶上傳視頻到發佈微博這一過程的體驗。

提速優化舉例


第一個是順序上傳。如今順序上傳的過程通常是二進制切片,切片後依次上傳,整個系統延遲會比較長,作並行上傳時,例如兩個進程同時上傳,會比順序上傳提速一倍。



在作並行轉碼時,至關於把視頻作成二進制分片上傳後,合併起來進行轉碼。轉碼時再將視頻切分紅不一樣時長的片斷進行分片轉碼,完成後合併視頻。這種方式下經過提升並行程度下降了延時。在邊傳邊轉方式下,客戶端上傳存儲後,立刻進行轉碼,客戶端操做與服務端服務並行,最後服務端會將源視頻、目標視頻分別合併。
2.4 微博視頻處理系統面臨的挑戰



咱們面對業務繁雜,需進行基礎服務優化的雙重挑戰。另外,微博業務具備很強的實時性,這就要求咱們每環節都得快速完成,包括咱們實現代碼的時間,接入業務方上線的時間。咱們必須實現一個低延時、高併發、高可用、高性能的視頻轉碼服務。



視頻轉碼服務自己須要大量計算,須要大規模的集羣支持這項服務。咱們面臨的另一個挑戰就是對大量集羣的管理。因爲咱們使用了分片轉碼,邊傳邊轉的優化方式,一個視頻切成十片,轉碼量會變成十倍,這致使轉碼任務量陡增,同時也會產生一個更細粒度的調度。切片給咱們帶來更加複雜的任務依賴關係,咱們要管理切片、分片並行轉碼以及合併整個過程當中的任務依賴。過程當中步驟越多,失敗率越高,越要求系統有更高的健壯性下降失敗。



咱們今天主要講的就是如何實現一個低延時、高併發、高可用、高性能的系統,我將主要從如下幾個方面來講明。首先是高度靈活的配置生成系統,至關於將業務相關的東西從主系統中抽離放到配置系統中,使主系統專一於基礎性能優化和基礎服務。第二點要講的是基於DAG的邏輯組織框架即用工做流引擎去組織任務之間的依賴。最後會講一下高可用、高性能的任務調度器對系統的重要做用。
3. 微博視頻轉碼服務架構設計


3.1 木林森


高度靈活的配置生成系統


對於靈活配置,咱們取名爲木林森。它是一個基於樹形結構的規則引擎,即咱們的配置結果都是樹形結構,多棵樹便可組成森林,因此咱們取名爲木林森。木林森支持靈活的配置生成。微博有些業務場景下產品方只要求快速而不在乎視頻輸出屬性,這時咱們能夠直接使現有輸出業務與輸入業務鏈接完成業務接入。用這種方式能夠提高新業務接入效率。下面是一個簡單的示例。


如圖,例如咱們有微博原生視頻接入業務,如今要接入的億幕視頻但願與原生視頻有相同的輸出。此時咱們在輸出業務如下到轉碼輸出都不須要改變,咱們只須要將節點鏈接,輸入的億幕視頻就與微博原生視頻有了相同的輸出。只需經過後臺點擊配置就可將視頻接入。右圖所示是微博視頻的輸出配置。


複雜場景下,原生視頻,秒拍視頻,VIP視頻的輸出業務配置如圖。不一樣用戶端視頻通過系統輸出的視頻是不一樣的。經過配置可完成複雜場景下的業務邏輯抽離。
3.2 DAG


基於DAG的邏輯組織框架

咱們本身實現了一套工做流引擎框架來支撐咱們的業務,首先介紹一下框架的思想。咱們是基於Java開發的,這裏用Java舉例。對於通常的上傳系統,代碼實現只有下載、轉碼、上傳的過程。在這一段代碼的基礎上,咱們要實現分片轉碼,邊傳邊轉等複雜的邏輯流。最簡單的方法就是咱們將通常上傳的代碼複製改動,這時咱們的方式如右圖。上傳過程變爲下載,切片,將切片結果上傳,下載切片,切片轉碼,上傳切片,而後使這個過程循環往復,這時可多臺機器並行工做,最後將切片合併。因爲過程複雜,全部咱們但願能用有向無環圖鏈接組織,將基礎服務固化,經過腳本將不一樣功能組織起來。這時咱們不管下載文件轉碼上傳仍是分片上傳,只需簡單鏈接便可,兩個下載之間的代碼是不須要改動的。咱們將可固化的部分固化,將代碼拆成一個個可獨立執行的閉包,經過DAG管理包與包之間的關係,在DAG內部實現閉包的執行。這就是咱們關於DAG框架的想法。



這是咱們轉碼服務的圖示。如圖中,Center部分就是中央調度的服務,Runner部分是執行轉碼任務的服務,videoTrans是DAG組織任務間關係的腳本。咱們的腳本經過Groovy實現。框架名字叫作Olympiadane,是經過Groovy引擎執行連成的關係,其中的Group是可獨立調度的單位,即圖中白色的部分。任務先通過調度器,調度器根據狀況分發到執行器,執行器內部根據先後依賴關係順序執行Task,在此例中就是下載,轉碼,上傳。另外一臺機器也是同樣的。這樣就實現了執行流與業務之間的解耦,若是要接入其餘的新服務的話,咱們只須要再實現一個Task,將此Task的依賴關係放入腳本便可完成。另外經過腳本生成的就是圖中的Job。這是咱們DAG架構。



實現DAG框架後,能夠經過腳本快速接入支持業務,因爲腳本變更但Feature不是常常變更的,因此Feature可在腳本間共用,也能夠獨立測試,這樣咱們即可以完成可組裝的獨立組件。這些獨立組件具有能夠獨立測試,易擴展,易部署,高性能的特性。



這裏描述的是DAG的過程。前面咱們提到的分片轉碼,過程分是下載,切片,上傳分片結果幾步。



例若有三個機器同時並行完成下載分片,轉碼,上傳結果的工做。當並行過程結束後,會有一個新的依賴關係,如圖中,下載全部分片,合併轉碼後的視頻,不一樣清晰度的文件都是在不一樣機器上並行工做的。這是對咱們轉碼服務優化中,經過DAG組織的一次實踐。



如圖中,灰色的部分變成了綠色,這表示這個過程是能夠觀測的,這也是經過DAG方式實現的一個優點。咱們能夠觀測任務執行到了哪一步,也能夠更快的定位出現問題的地方。另外,因爲咱們進行了拆分,能夠對獨立Feature進行DAG切面,例如咱們能夠統計它的耗時,這樣咱們能夠知道哪一種類型的業務耗時較長,也有助於觀察系統的穩定性。



在DAG的優化方面,咱們經過字節碼編譯技術作到了腳本快速執行。另外咱們引入了一些Protostuff技術快速完成資源存儲。
3.3 調度器

高可用、高性能的任務調度器

咱們經過木林森將業務系統抽離出來,經過DAG系統將實現時的依賴關係抽離,所以咱們須要一個好的調度系統來支撐。因爲咱們進行了切片,所以調度任務達到了萬次每秒。咱們也會須要更細粒度的調度任務,比起粗粒度的調度,對基礎組件性能要求更高。咱們對調度器的另一個設計目標就是調度佔比要低於百分之五,這就意味着系統損耗更低。這對調度器有極高要求,咱們要使百分之九十九的調度任務在10ms內分派到對應機器,而且咱們但願它的調度是最優調度,即能準確把任務分派到空閒機器。



在設計調度器時咱們也作了一些思考。咱們對中心化調度器和非中心化調度器作了對比。中心化調度器的調度準確度高,它將資源隊列信息放到中心化存儲中,對監控更親和。可是它的資源依賴較多,咱們將隊列放到了資源中,所以資源訪問讀寫中會產生必定依賴,也會有必定性能損耗。對於去中心化調度器來講,它的擴展性更強,可是它存在調度不許確的問題。最終咱們選擇了中心化調度方式。


上圖是調度器調度過程。左邊是調度器,右邊是執行器。調度器和執行器之間經過心跳註冊,心跳時間是可配置的。註冊完後會將機器信息放到機器隊列,中心資源中有一個任務優先級隊列,咱們能夠對不一樣任務映射不一樣優先級。另一個是機器空閒優先級隊列,就是咱們將機器空閒度映射爲優先級。在派發時,咱們會取到高優先級任務,取到空閒度優先級高的執行器,而後將任務派到指定機器,便可將任務放到執行隊列中。執行隊列的重要做用在後面會講到。執行結束後,會進行一次回調,從執行隊列中移除任務。咱們經過三個隊列完成任務調度,因爲存在資源依賴,因此咱們對這些資源進行了哈希計算,不一樣機器可使用不一樣資源,只要資源知足就可分派任務。



可是這裏會有一個問題。心跳會彙報狀況,但它會有必定延遲,若是Executor與資源中存儲的狀態產生差別,任務可能會被分派到一臺沒法工做的機器。爲解決此問題,咱們設計了一個帶鎖的雙發調度。與以前介紹的相同,咱們依然從隊列選擇機器。不一樣的是,咱們會在空閒優先級隊列中取到最優的同時,取一個隨機機器去完成分派。分派後,執行器會再一次調用調度器確認由誰完成任務,再去執行。當最優任務不可執行時,另一個機器可完成任務。這樣,咱們就能夠實現百分之九十九的任務在10毫秒內完成分派的目的。一樣的,帶鎖雙發調度也會有哈希計算的存在。同時,咱們會使用WatchDog觀察執行隊列中的任務是否在規定時間完成,若沒有完成,咱們會從新觸發調度器分派任務。這樣咱們能夠有效減慢失敗率提高。



經過以上設計,咱們的調度器能夠實現毫秒級派發。對於微博業務來講,可能會出現緊急大流量出現,咱們在設計時也考慮了水平伸縮方式,使它支持彈性擴縮容。經過WatchDog機制,咱們能夠實現宕機自動摘除。在實際應用中,咱們天天都會有機器擴縮容,咱們的作法是讓待擴容機器不接受任務,先完成已有任務,再作機器擴縮容工做。但這樣作還會有未完成的任務存在,經過WatchDog機制,咱們能夠確保這些任務從新分派完成。同時咱們實現了4個9可用性。
3.4 部署


在轉碼服務部署方面,咱們在兩個IDC部署了徹底相同的兩套資源,它們有獨立的域名,獨立的部署。這麼作的好處是咱們能夠在兩個機房間隨意的切流量,任一機房出現問題,咱們均可以切換,可是兩個機房的部署並非一比一的冗餘。咱們常備的機房是一個大規模集羣,另外一個機房是一個小規模的,或許只有常備機房十分之一的量。兩個機房在使用時能夠分開,例如咱們轉一些不影響用戶發博的轉碼輸出時,可使用小機房完成任務,這樣大機房出現「災難性」狀況時,能夠把流量切到小機房。固然小機房是不能知足那麼大流量的,可是調度器自己的隊列有堆積的特性,能夠將堆積的任務慢慢執行。沒有大量機器冗餘能夠充分利用機器。
4. 總結



接下來,我將全部內容作一個總結。經過轉碼服務的優化提高,咱們總體轉碼提速了5倍,集羣利用率標準差降低了百分之五十。這裏的標準差指因爲分派任務不合理,分到不一樣悠閒度的任務致使機器CPU利用率忽高忽低的狀況。經過好的調度方式,對集羣的利用率標準差有很大下降。另外,咱們業務支撐的效率也成倍提高。咱們經過各類方式進行解耦,將變化大的和變化小的分開放到不一樣位置。


在服務架構設計開發的過程當中,咱們使用了不少並行手段,包括機器並行、進程並行、線程的並行以及算法、CPU核的並行等,經過這些手段發揮機器最大的價值。今天咱們設計的目的是一個低延時高可用的系統,咱們用到的並行上傳,並行轉碼,極致上傳等手段都用了算法上分治、遞歸、貪心的思想。在高可用方面使用了高內聚低耦合的思想,用到了動靜分離、自動容錯、異地多活的手段。最後想和你們分享,咱們在作系統架構、設計優化不知道該如何實現的時候,就能夠無腦的把這些高內聚低耦合、空間換時間等常見的思想往系統上套,或許就能夠獲得想要的結果。優化架構並非多麼複雜深奧的東西,咱們要去思考的是前人總結的這些手段在咱們本身系統上的可否達到效果,若是獲得了滿意的效果,那麼這些思想就會轉化爲咱們本身的東西。
相關文章
相關標籤/搜索