博客 / 詳情

返回

微博視頻處理系統的雲原生之路

本次LiveVideoStackCon 2021 音視頻技術大會 北京站邀請到了新浪微博視頻平台架構師——黃陽全,他將為我們介紹微博視頻處理系統的架構演進與雲原生之路上的探索,為什麼選擇自建,以及如何實現基於原有基礎服務的FAAS平台。為嘗試雲原生架構模式的開發者提供參考。

文 | 黃陽全

整理 | LiveVideoStack

大家好,我是來自微博視頻平台的黃陽全,今天分享的主題是微博視頻處理系統雲原生之路。

我在2017年加入微博研發中心,負責微博視頻基礎組件的開發與維護,多次參與了微博視頻架構升級,主導了微博視頻中台的建設。目前正在建設基於雲原生架構的微博視頻處理系統。

圖片

本次分享主要分為4部分:

1.背景介紹:主要介紹微博視頻,微博視頻處理系統,微博視頻處理系統所包含子模塊,以及它的特點;

2.原視頻處理系統架構:針對微博視頻處理系統所具有的特點,我們設計出基本滿足需求的原架構,但是隨着業務的發展,逐漸發現了原架構的短板;

3.FaaS平台的探索與實踐:針對短板,我們在雲原生領域開始瞭如火如荼的FaaS平台的探索,在原基礎服務之上開發出瞭解決業務痛點的FaaS平台;

4.總結與未來展望。

一、背景介紹

圖片

隨着4G/5G技術和設備的不斷普及,越來越多的用户選擇通過視頻或者直播來記錄生活,傳遞知識,表達觀點。

微博作為一個即時分享平台,視頻所佔的比例也越來越大,目前微博視頻的日發佈量已達到百萬級,日播放量也早已突破十億級。

圖片

圖示為一個微博視頻從生產到消費經歷的整條鏈路:

首先視頻創作者從手機、PC等設備上傳視頻或是開啓直播,視頻處理服務接收請求後進行視頻的處理。處理完成且審核通過後,視頻發佈,最後用户能通過播放服務看到視頻。

下面放大視頻處理服務部分(黃色部分)。

圖片

視頻處理系統包含四個子模塊:視頻轉碼,視頻內容理解,直播錄製和轉碼實驗室

1、視頻轉碼:對於用户上傳的視頻,我們需要將視頻轉碼成不同的清晰度(1080p、720p等),以滿足不同場景下用户的播放需求。對於用户來説,上傳後視頻越快發出,體驗越好,所以視頻轉碼有速度要求。另外視頻微博的上行有熱點特性,需要有較好的峯值應對能力。

2、視頻內容理解:負責提取視頻中的內容信息,轉換成結構化數據,助力於業務發展。內容理解具有資源多樣,算法多樣,服務多樣的特性。

3、直播錄製:從源站拉取直播流,轉碼後的視頻存儲到文件服務,以供用户點播觀看。

4、轉碼實驗室:顧名思義,是各種轉碼算法、圖像算法、內容理解算法的試驗田。轉碼實驗室是離線處理任務,對實時性要求不高,可能白天需要驗證的算法,晚上跑,第二天能得出結果就可以。

圖片

綜上所述,微博視頻處理系統具有大流量、實時性、核心服務、峯值明顯、在線/離線同時存在、資源多樣的特點。

二、原視頻處理系統

圖片

對於視頻轉碼來説,保證轉碼的效率是至關重要的。

這是一個整文件轉碼和分片轉碼的對比示意圖,整文件轉碼分為下載、轉碼,上傳。分片轉碼將下載好的視頻分片後並行處理,從而提高轉碼速度,可以看到分片轉碼速度遠優於整文件轉碼速度,特別是轉碼大視頻文件時,這也是業內通用的解決方案。

但是分片轉碼也帶來了新的挑戰:

1、流程編排複雜:如果採用傳統的編碼方式進行分佈式分片並行轉碼是比較困難的,另外還要考慮失敗超時重試等情況,整個流程會非常複雜。

2、高併發,低延遲:在微博的場景下,結合前面講到的微博視頻的特點,我們還有高併發低延遲的挑戰。

有的同學會疑惑,視頻上傳這種上行接口大概是幾百qps,怎麼會達到高併發?這裏解釋一下,假如微博的上傳qps是100,一個視頻分成100個分片,需要轉出10個label的清晰度,那麼系統內部需要承載的qps將被放大到10w。

為了解決這兩個問題,我們開發出了流程編排引擎和高性能的調度器。

圖片

首先是DAG有向無環圖的框架和Olympiadane。我們採用與Java親和度比較高的Grovvy定義DAG流程。

這是DAG編排後的分片轉碼流程圖,每一個task(綠色節點)是一個單獨的實現類,以此解耦流程和任務,DAG還提供重試重做,可視化的功能。

圖片

有了流程的編排,還需要將任務下發到機器上執行,於是我們開發了TaskScheduler任務調度器。

任務調度器採用任務優先級隊列和機器優先級隊列相結合的方式,將調度性能優化到一次redis命令執行,支撐轉碼10w級併發,毫秒級調度的需求。

此外,TaskScheduler還具有雙發調度,任務組發、水平伸縮、宕機自動摘除,忙時堆積等特性。

圖片

這是任務調度執行的全景圖,有了DAG和TaskScheduler,視頻處理任務由DAG描述依賴關係,通過調度器調度到Worker上執行。

以上是原視頻處理系統的一些關鍵設計。

那麼,隨着業務的發展,我們遇到了哪些挑戰,系統又隨之顯露了哪些短板呢?

問題一:資源整體利用率不高

圖片

算力緊張,但是資源整體利用率不高:業務高速發展同時伴隨着越來越多新算法的不斷落地,對資源的需求也越來越多,不斷舔磚加瓦的同時,我們也在審視當前的服務資源使用情況。

圖片

右圖是某一時刻服務資源利用率的橫截面圖,由於不同的服務模塊具有資源差異(計算密集型業務/內存密集型系統),和運行時段的差異(業務流量高峯期/凌晨流量低谷),雖然我們儘量做到局部最優,但還是很難達到全局最優。

圖片

這是線上某台轉碼機器的CPU利用率的截圖,可以看到,機器CPU利用率存在明顯的波峯波谷。高峯期,機器利用率可高達95%,但是低谷期,利用率還不到10%

圖片

在評估服務資源的時候,為了保證系統的可靠性,往往需要根據服務的峯值進行評估,另外還要預留一定的冗餘度。

雖然我們已經做了基於公有云的晚高峯彈性擴縮容,比如每天晚上8點開始擴容,到凌晨流量下降時再縮容。但整體看來,服務還存在着巨大的冗餘與浪費

圖中的金幣部分就是浪費的的資源。

問題二:開發運維效率不高**

圖片

需求緊急,但是開發運維效率不高。

圖片

這是一個真實的案例,產品組大半夜發來消息:“算法Demo已經跑通了!似乎可以上線了!明天能灰度了嗎?”。

但後端開發人員遇到的問題遠不止於此:

1.算法代碼如何轉成工程代碼,有沒有坑?

2.代碼寫在哪個工程裏?會不會有衝突?後期怎麼維護?

3.灰度功能在哪兒加?

4.如何保證系統的可用性?

5.流量熱點怎麼應對?

6.擴縮容怎麼做?

這些問題都需要考慮。

圖片

在當前服務模式下,從算法到上線,再到有數據,需要經歷哪些步驟呢?

首先,需要將算法翻譯成工程代碼,因為負責算法的同學關注算法本身的正確性多於工程方面,所以他們提供的算法可能並不能直接應用於工程。然後進行適配開發,加入到現有的工程中,假設轉碼後有幾萬行代碼,這就需要考慮AB測試,兼容性,後期維護,高可用等問題。通過測試後,即可打包為線上鏡像並上線,上線完成後,還需要考慮服務保障、擴縮容等,最後才能得到效果數據

總結可得在開發效率方面遇到的三個問題:

1、開發縱深太深,新手難以上手;

2、開發流程複雜;

3、運維難度大。

圖片

如果無法妥善處理這三個問題,結果就會如左圖所示只有工程開發在默默挖坑。

三、FaaS平台的探索與實踐

現有的服務模式似乎難以解決資源利用率低及開發運維效率低的問題,於是我們開啓了對FaaS平台的探索與實踐。

圖片

FaaS的全稱是Function as a service,是為用户提供開發、運行和管理的函數服務平台

以承載”函數”的方式來啓動基礎應用框架,並對應用實現資源編排、自動伸縮、全生命週期覆蓋等保障,從而實現雲服務的Serverless。

由IaaS發展到現在的FaaS(左圖),開發者需要關注的內容越來越少,可擴容單元越來越小。

圖片

介紹了FaaS後,我們將遇到的痛點和FaaS平台可以解決的問題進行以下對比。

痛點一:開發縱深太長;FAAS平台可以消除技術壁壘,理論上只需要瞭解函數的輸入輸出就可以,開發人員沒有其他心智負擔;

痛點二:開發流程複雜;FAAS可以提供部署、發佈、監控“一條龍”的服務,並提供穩定性保障;

痛點三:運維難度大,體現在服務保障,宕機處理等方面;FAAS平台免運維,全託管;

痛點四:資源整體利用率不高;通過平台化的思想,整合資源,共享冗餘,實現按需調度,從而提高整體資源利用率。

圖片

對於FaaS平台的選型,我們有三個選擇:雲廠商、開源FaaS框架和自建。

1、雲廠商:由於只能覆蓋公有云的場景,微博場景下暫時不考慮;

2、開源FaaS框架:根據對常用FaaS框架進行調研的結構顯示,在場景、語言以及適配上有一定的侷限性,現有系統遷移起來難度比較大,而且有些框架還不夠成熟。

於是我們選擇了自建FaaS平台,通過複用現在的基礎設施和框架,打造適配微博處理系統的FaaS平台。

圖片

以下是基於原框架基礎構建FaaS平台的步驟:

第一步,將DagTask抽象為function,使其能夠獨立部署運維,上文提到DagTask是單獨的實現類,與原項目代碼有耦合。假設內容理解工程中有幾十個task,會使工程代碼量膨脹,增加開發人員的心智負擔。而在Function的設計中,開發人員只需關注輸入輸出,開發更簡單高效;

第二步,原DagTask會依賴整個服務的部署,轉碼時整個服務中會部署幾十個task且task的升級和擴容都不能獨立進行。Function的設計中完全解決了這一問題,它提供了函數級別的部署運維,可獨立伸縮。

另外,原DagTask僅支持Java,Function不限制語言,目前已支持了Java、go、python,為算法人員提供便利。

圖片

第二點升級是將原DAG流程服務化。原DAG流程採用grovvy描述、SDK依賴的方式。那麼在升級DAG流程時,需要上線兩次,首先全量上線class文件,否則當task被調度到沒有此class的機器上時,會出現“class Not Found”。

WeiboFlow採用yaml文件描述DAG,通過服務化管理DAG版本,對版本迭代更友好。

此外,由於原DAG流程採用了grovvy描述、SDK依賴的方式,與項目代碼耦合。服務化之後可與項目代碼徹底解耦。

圖片

完成以上兩個重要改造之後,基本形成了FaaS平台雛形。

將FaaS平台分為兩層,第一層是服務化的WeiboFlow函數編排層,負責函數的編排流程管理,第二層是WeiboFunction提供的雲函數層,負責具體的函數調度執行。

圖片

這是FaaS平台的任務調度鏈路圖,主要分為三部分:

1、WeiboFlow,上文提到是DAG服務化的版本,主要功能是對DAG進行版本管理及DAG的執行。

2、WeiboFunction,主要負責函數管理及部署管理,其中的重要組件Task Scheduler是複用了原有的Task Scheduler從而進行函數的調度。

3、具體執行的node節點,其中的重要組件FunctionLet負責接收任務,與WeiboFunction保持心跳,上報函數信息和機器槽數。

藍色虛線表示任務的調用鏈路,應用可直接調用WeiboFlow的submit接口提交完整的轉碼流程或內容理解流程,也可以直接調用WeiboFunction執行某一個函數。

WeiboFlow收到調用請求後,開始執行DAG上的節點,每一個節點可對應一個Function,調用到WeiboFunction執行,Function收到請求後,使用Task Scheduler下發調度任務,將優先級最高的任務和最優的機器進行匹配後調度到具體的機器上執行,具體的node,FunctionLet收到請求後進行函數執行及回調。以上就是整個調用鏈路。

介紹完FaaS平台後,再回到最初的問題,它是如何解決以上兩個問題的呢(資源利用率低、開發運維效率低)?

圖片

圖片

3.1 提高資源利用率

3.1.1 整合管理所有資源

FaaS平台將不同機器型號,資源類型統一抽象為槽數,比如8核16G抽象為2000個槽,16核32G抽象為4000個槽,同時將GPU和FPGA設備也抽象為相應的槽數。還可對此轉換公式進行配置,統一了資源的度量衡。

通過這一層抽象,FaaS平台能夠統一管理調度多類型的資源。

FaaS平台還實現了動態資源標籤化,以此實現機器資源的隔離,結合上文提到的多隊列調度器,即可充分利用資源。

3.1.2 動態擴縮容

圖片

FAAS平台實現了基於函數維度的動態擴縮容,左圖顯示了原晚高峯的擴縮容,右圖顯示了基於函數的動態擴縮容。

得益於函數啓動的速度更快,動態擴縮容更貼合服務權限。

我們將動態擴縮容功能分為四層:決策、聚合、Function擴縮容和Node擴縮容。

決策層:在做服務冗餘度決策時,可根據服務冗餘量或當前隊列堆積情況,動態計算服務冗餘度,還可根據時間策略,通過某一時刻的流量情況進行決策,人工干預也算作一種決策。

聚合層:聚合決策層下發的不同策略後做出最終的決策——服務最終的擴縮容策略。

Function擴縮容:在服務容量足夠的情況下進行動態的函數擴縮容。

Node擴縮容:當服務容量滿載,有些服務沒有空餘槽時,會觸發Node層的擴縮容。Node層由微博的DCP平台打造而來,目前DCP平台可以達到5min,2000台機器,基本滿足我們的要求。

圖片

動態擴縮容能夠提升高峯期的資源利用率,那麼如何解決常備資源量以下的浪費呢?

圖片

方式一:分時複用,在A服務的冗餘度達到某一水平時,對A服務進行自動縮容,再部署B服務,以此達到分時複用的目的。

圖片

此方法可應用於轉碼服務和轉碼實驗室服務(無論在線或離線)。白天轉碼實驗室的任務由少量機器處理,先進行堆積,到凌晨時,轉碼服務縮容,部署轉碼實驗室,消耗隊列中待處理的任務。

圖片

方式二:挖礦。空閒資源代表“礦”,執行完即銷燬的Function代表“挖礦工具”。

執行完即銷燬的Function:雲函數的服務模型分為兩種,常駐進程型和用完即毀型。常駐進程型的函數不會被銷燬,而用完即毀型的函數在一次調用完畢後就會被銷燬。我們將Gif轉碼任務設計為用完即毀型,因其運行週期較短,Gif任務也常作為“挖礦工具”。

圖片

如何“挖礦”呢?

這是1~5,五台服務器,Node1有4000個slots,Node2有3500個slots。假設5台服務器都部署了A服務,此時A服務只佔3000個slots,那麼會出現1000個slots的冗餘。如何減少冗餘呢?

圖片

假設要對Node1~4進行挖礦,只需要給1~4打上B的tag,此時調用器通過心跳感知這些機器,會將函數B調度到機器1~4上執行。

如果Node1空閒1000個slots,而函數B的一個請求佔100個slots,那麼Node1上可以並行跑10個函數B,Node2可以並行跑5個函數B,通過調用器實現“指哪挖哪,哪裏有礦挖哪裏,有多少挖多少”。

圖片

進一步探索“挖礦”——如何更高效率地“挖礦”呢?

執行完即銷燬的function採用冷啓動的方式,(如圖)先start up,再run stack,如此反覆,每次都需要重新start up,累積下來對機器的損耗較大。

於是我們進行了以下優化,採用熱啓動的方式,一次函數啓動後,如果在最大空閒時間內有請求進來,就繼續執行任務,不被銷燬;如果超過最大空閒時間內無請求進入,那麼函數運行環境會被銷燬,下次任務到來時需要重新啓動。通過以上步驟達到連續挖礦的目的。

圖片

優化後的效果如圖,使整個服務的資源曲線更加貼合服務的流量,提高了資源利用率。

圖片

圖片

3.2 提高開發運維效率

1、FaaS平台提供了開箱即用的模板工程實現統一工程化及標準化。

一個雲函數對應一個gitlab的項目,函數開發與發佈都圍繞單個項目進行CI/CD,高效且安全。從而使開發人員更關注業務邏輯,達到提高開發效率的目的。

圖片

2、FaaS平台提供了雲函數的高可用保障。

這是任務從WeiboFunction調度到具體機器上執行的細緻流程圖:

在FunctionLet和Function之間利用QueQiao進行通信,FunctionLet在接收到任務的時候,寫入TaskQueue,Function讀取TaskQueue進行函數邏輯處理,處理完畢後將結果寫入ResultQueue,FunctionLet讀取ResultQueue中的結果,並返回。

這樣的設計如何提供高可用保障呢?

1)假設WeiboFunction宕機或者脱網導致回調失敗,此時無需重新運行所有任務,已執行完的任務會將結果寫入ResultQueue中,FunctionLet回調失敗後也會將回調失敗的任務重新寫入ResultQueue中,等待WeiboFunction恢復後,重新將執行完成的ResultQueue進行回調,已執行完畢的任務不會丟失或被再次執行。

2)假設FunctionLet上線重啓或者服務異常,已執行完畢的任務也會被寫入隊列,等待FunctionLet恢復後重新回調。

3)假設Function掛了,FunctionLet將停止接收新的任務,FunctionLet對Function有具體函數的保護,重新啓動函數,執行Queue中任務進行回調。

那麼假設Node節點整個都掛了,且處於不可恢復的狀態時,執行完畢的任務會丟失嗎?

圖片

答案是否定的,我們在Task Scheduler層設計了派發重試及故障轉移的功能。除了node上各個組件的高可用,還保證了node級別的高可用。

當任務被派發到執行機器上時出現了超時的情況,任務會從Task Scheduler的執行任務隊列中取出並選擇一台當前活躍而且空閒度最高的機器重新派發,以實現派發重試的功能。

當Node無法恢復時,會被移出執行器隊列,後續的任務不再被派發到這台機器,以實現故障的轉移。

WeiboFunction還提供了Function級別的調諧保活機制,根據申明的服務節點個數重新找到合適的節點,啓動服務,以保證服務達到申明的最終狀態。

圖片

3、下沉通用功能。

我們將常用的比如限流降級,AB測試等下沉到平台來實現,這樣用户不用自己實現,只需要在FAAS後台通過配置的方式即可操作。

1)AB測試:可通過WeiboFlow的DAG配置來實現,如右圖所示,將80%流量打到圖1,20%流量打到圖2,開發人員通過配置即可實現流量的分發。

2)任務動態優先級:每個任務都有對應優先級,在轉碼服務中,假設用户發博的任務是480P,那麼此480P任務的優先級就相對較高,可以通過動態調整任務節點的優先級,並配合調度,先執行優先級高的任務。

3)任務動態權重:一個h265的任務通常需要佔用更多的slots,此時可以通過任務動態權重功能達到資源的平衡利用。

4)限流降級:為每個節點配置限流降級的閾值。

5)錯誤處理:節點錯誤後可以配置重試頻率及重試次數。

6)大小圖、父子圖:針對複雜的流程圖,提供了大小圖和父子圖的方式,每一個節點都有可能是另外一個完整的圖,可以理解為對節點進行foreach的操作,分片完畢後,如有100分片,就對分片進行foreach循環,每一個循環都有一套處理邏輯,而處理邏輯是可以複用的,這就可以通過大小圖的方式解決。

7)多種語義控制:目前提供了pass/foreach/return/suspense/choice等語義,可支持複雜的流程編排。

圖片

4、Faas平台提供了多維度的可觀測性。

右圖1是執行完畢的轉碼DAG圖,截自Weibo Funciton後台,展示了整個執行鏈路,節點出現問題時會變紅,便於追蹤鏈路,排除故障。此外。每個節點還有統計信息,執行時間、橫向或縱向的Metrics。點擊每個節點,會出現右圖2所示的詳細信息,其中包含整個執行關鍵日誌,便於用户調看。

圖片

5、FaaS平台重建了開發流程。

開發人員在代碼編寫完畢後,通過本地測試構建鏡像,註冊或升級函數,再進行遠端測試,最後發佈函數,函數即可彈性執行。

通過用户維護WeiboFlow流程或者其他事件可觸發執行函數。

四、總結與未來展望

圖片

微博視頻處理系統在具有實時性、大流量、核心服務、峯值明顯、資源多樣、在線/離線等特點的背景下,為了解決高併發,低延遲及流程編排複雜的問題,我們開發出了DAG編排引擎及任務調度器。

但隨着業務的發展,陸續出現了資源利用率低,研發運維效率低的問題,於是我們開啓了雲原生架構中的探索,開發了高彈性,全託管的FaaS平台,通過資源整合、按需調度、減小開發粒度,下沉通用能力以解決利用率和運維效率的問題。

圖片

最終達到的效果,主要分為兩方面:

1、降低成本:集羣負載標準差優化30%,視頻轉碼彈性成本了降低44%,通過分時複用、挖礦的方式將算法迭代週期從40天優化至6天。

2、提高效率:支持算法的上線週期由天級或者周級優化至小時級。舉一個真實的案例,在奧運會期間,我們收到了識別某logo的需求, 從中午接到需求到下午上線完成得到數據,僅用了幾個小時。

圖片

未來,我們希望FaaS平台能夠支持更多的場景,比如在WeiboFunction增加負載均衡層,從而支持傳統微服務場景。

其次是冷啓動優化,雖然目前已經支持常駐內存的方式減少冷啓動帶來的消耗,但在需要頻繁冷啓動的場景下,還會造成較大的損耗,未來我們會在冷啓動方面投入更多時間精力。

最後是智能化運維,在FaaS的運維場景下加入服務畫像,根據服務畫像動態調整服務容量,達到更高的利用效率。

以上是本次的分享,謝謝!


圖片

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.