直播平臺的高併發架構設計


目錄(?)[+]

興起及現狀

日常生活用手機來看視頻的次數越來越多,時間越來越長,看的內容也是種類越來越多。包括最近從3月份美國開始火起來之後,國內也在火的移動視頻社交類。這個也是我們現在在重點切的一個垂類,這個垂類爲什麼現在會火?我們總結下來一部分原因是因爲它的娛樂性很強,延遲很低,和主播有強互動的可能,所以越來越多的人在關注。國內現在起碼有幾家已經上線,有幾十家正在聯繫準備上線,其中總歸會有幾個火起來的。


這就是對我們現在接觸到的這些行業做了一些分類,有綜合類的,就是用戶產生內容,以娛樂爲主,不對用戶產生的內容做強的劃分。會有一些建議,但是不會強制要求。還有一部分行業性比較強的,像財經、體育,教育這些類。

還有就是最廣泛的秀場類的,這個盈利模式也是最清晰的,它的量特別大,主播依賴特別強的這種業務。這部分廠商的核心需求很明確,大部分來自於他們的業務需求,他們擅長做的是裝機量,保持高日活,保持主播和用戶之間的黏性,然後怎麼做商業化,商業化已經讓很多人頭疼了,這些事情夠他們忙,而且是他們擅長的。

但是在多媒體的這部分,門檻很高,以前做點播業務,像兩年前我在做媒體雲的時候,當時都是點播的業務。做到後面,我覺得點播業務其實並不像想象的那麼難,你想你有一個穩定的存儲,找一家靠譜的CDN,然後找一個大概能用的播放器就做出來了,這有什麼難的呢?你可以找雲服務公司,也可以找外包,或者你自己招一個人都能做。但是現在發現到了移動,尤其是3月份移動直播火起來之後,這個門檻突然變高了。因爲內容產生方變成了移動端,後面我會詳細說。

核心需求

先說一下這個核心需求爲什麼會出現。大家在看移動直播的時候,如果有人關注的話,會發現那些主播經常問的一句話就是“卡不卡,是不是又卡了,我要瘋了,又卡住了”。你們看點播的時候,看短視頻的時候,不會有人這麼問吧?不會說你們看短視頻,它又卡了,這種問題是最近纔出現的。真正的客戶都已經返回這種問題了,說明流媒體的門檻又變高了,所以他們對流媒體的需求是在增長的。那我們就看一下這些需求都有哪些。


1、首先內容產生方就是推流端,現在主流的iOS安卓ios比較簡單,就是那個幾個機型,基本大家適配都很好。但是安卓的碎片化是非常嚴重的,大量的精力都需要做對安卓的適配,而且軟編耗電量普遍非常高,手機用了一會就會發燙,都擔心會不會爆炸。用戶體驗就是在不同的網絡情況下,上傳的視頻有可能會卡,有可能不連貫,報各種各樣的錯誤,這個是作爲一個開發者他自己不可能去適配的。說白了從用戶那邊提的需求就是推流端不能卡,畫質要好,不能太燙,這是我們接觸到的客戶真正提的問題,是我們從有點偏技術的角度抽取出來的,它背後對應的是哪些事情。


2、然後是分發網絡。分發網絡其實躲在一個很後面的地方,用戶其實看不見的。真正對分發網絡提需求用戶也提不出來,所以基本這部分需求都會提給播放端,提的需求也是不能卡,不能花屏,首屏一定要快,一點就要看到,還不能把延時弄的太大。其實這些很多都是和源站分發網絡有關係的,只是用戶看不到這個需求會跟後面的播放器接在一起。


對這個需求我們做一些抽象來說就是用戶的可觸達性要好,我們的CDN節點要在全區域、全運營商有覆蓋,包括教育網。有很多人,像那些小運營商都會忽視教育網,我們也遇到過這樣的例子,教育網確實不好接,因爲節點不夠多,這其實不是什麼難點,只是一個坑,注意到了就能做到。低延時的操作大部分來自端的配合,服務端只要是做好緩存,保證這個數據是連貫的。如果要丟數據的話,把關鍵幀保留好,丟GOP中間那些PB幀,主要是在端上會收到。


首屏時間,就是用戶點開就要看,以前那些開源架構就是rtmp server,它是做不到一點開就能看的,現在一些開源的國內資源寫得也比較好了,可以看到。我們是自己開發的,所以也花了一些工作,能保存之前的關鍵幀的信息,用戶一點開就能看,這個就是很細節的東西了。如果這個做不好的話,會黑屏、綠屏,或者是半天看不着圖像。


3、在播放器這邊也是我們在接業務的時候,遇到用戶投訴最多的,因爲所有的問題都是在觀看的時候體現的,所有的雷都得是播放器的同學去扛。這個需求也是不能卡,不能延遲太高。如果延遲高了,要追回來,追的時候聲音不能變,最好是追的策略也能自己控制,這是用戶真正提出來的需求。


對於我們來說,要滿足這些需求,我們需要做好多分辨率的適配,保證好流暢性,保證好我們追趕的策略不會出現任何異常。所以這三個端很多是相互耦合的,像推流和分發在一起,要保障好用戶的流暢性和畫質,分發和播放器在一起要保證好低延時和播放的流暢。所有的這些需求裏共同的一點就是不能卡,後面我們在設計方案的時候,也是重點考慮怎麼能做到不卡。

解決方案

這個是我們這邊的系統架構圖。最下層是依託金山的雲服務,因爲我們已經有了很好的平臺,提供了我們計算資源,提供了存儲,提供了很多自建的節點,當然還不夠多,我們還是個融合CDN,然後提供了數據分析的能力。我們依託它做了橙色的這一層,就是我們自己的核心,流媒體直播,然後圍繞這個核心我們再做的回看點播、在線轉碼、鑑權、內容審覈。


爲什麼要做回看點播?因爲這不是一個短視頻錄播的項目,而是一個直播,直播就決定它的併發不會很高,內容不會很多,熱點比較少。如果你不回看的話,用戶很難維持它的日活,很難維護用戶黏度,所以用戶一定會要求做回看的。

爲什麼要做在線轉碼?推流端其實做了很多把更好的畫質想盡辦法傳上來的工作,投了很多人力來做。傳上來之後,觀看也在移動端,它不一定看得了。如果他看不了怎麼辦?我們就需要在線轉,在線轉碼其實承擔的更多更重要的事情。

鑑權,用戶都不想被盜鏈,尤其是推流的時候,如果我不鑑權,誰都可以來推,推個法lun功怎麼辦?這是必須要有的。內容審覈,現在我們沒有辦法幫他做到自動審覈,技術還不夠。現在做到的是截圖,按用戶指定的時間定期截圖,這樣的話,用戶就可以請一些外包來看是不是有敏感內容,是不是要下線,這個對於現在這種三四秒延遲的直播來說非常重要。你做不到的話,沒準政策因素你就做不下去了。

數據分析一部分是依託金山已有的,一部分是我們自己做的,因爲我們延遲性,時效性要求更高。客戶會經常大半夜突然提出一個主播看起來特別卡,問你爲什麼,要是像以前那種方式,一個小時生成報表,然後出體驗圖,告訴他爲什麼卡了,客戶可沒有這個耐心。

我們現在基本能做到5秒間隔就出之前的各種問題定位,這個定位包括從源站收集的數據畫的曲線。還有從端上,如果端上用戶允許的話,推流和拉流端我們都會有上報數據,幾個曲線一擬合,我們就知道問題出在哪裏。所以現在不止是RD可以來查這個問題,我們很多售前都在承擔着幫用戶出這個圖的工作。


這個是介紹業務具體的流程圖,這個流程圖並沒有什麼特別,只是一般的流媒體的數據走向、各種請求。但是其中有一些坑我可以跟大家重點說一下,首先看一下直播發起流程,這肯定是由應用向自己的服務端去請求一個推流地址,這個推流地址他就用來向我們的流媒體服務器推,然後我們給它鑑權。

鑑權之後,它可以在參數裏選擇是不是要錄像。如果需要錄像截圖,或者需要HLS的分發,我們都可以幫他做,做完之後存到我們的存儲裏,這也是後面會提到的,我們各個業務之間在做隔離、分不同的優先級,這種後端的多媒體的處理儘量都會依賴別的服務,然後就是正常的結束流程。

這個是實際中遇到的一個問題,現在做流媒體,用戶推流,他想知道這個流結沒結束,一般互聯網公司做雲服務都怎麼做?都是給回調,如果這個推流結束了,我來回調業務方,讓業務方知道我結束了,你可以做你的邏輯了。

但實際操作中我們遇到了問題,就是業務方的服務器沒那麼可靠,我們可能過去時間特別久,有延時,有丟,或者他們的服務穩定性我們也確認不了,這其實就是一個雙方的耦合了。而且它的服務器,由於是我們來調,它的鑑權功能沒有辦法做得很複雜,他自己的服務器也存在安全漏洞。如果有人來攻擊他的話,他的整個業務流程的狀態全是亂的。

在試了幾家客戶之後,我們就改成另外一種方式,也是大家普遍都接受的,就是由APP和自己的Server發心跳,如果APP的網絡不異常的話,它自己結束它的Server肯定是知道的。如果異常的話心跳斷了,他也會判斷出是結束了的。而且我們這邊源站服務也會保證,你5秒鐘沒有數據就一定是結束的了,我們會把你的流給踢掉,這樣就能達到用戶的業務狀態也是穩定的,我們的流媒體服務也是穩定的,而且耦合也會比較少。

這是我們實際遇到的一個坑,這個其實不難,只是看現在普遍雲服務提供商還都是在用回掉的方式,所以我特別提一下另外還有一種可選的方式,效果更好。

播放的流程,播放器會先向他自己的服務請求播放地址,然後來我們這拉流,可以是鑑權也可以不鑑權,取決於它的業務形態。如果拉流失敗,我們有一些定製化的操作,他用RTMP來拉流的話,我們會告訴他具體是什麼錯,包括鑑權失效,鑑權參數錯誤,還是這個流有問題,我們都會在狀態告訴他的。這是之前用戶提到的需求,說是播放需要知道哪裏出了問題,所以我們儘量把狀態碼都特別詳細的返回給用戶。包括我們原站也有查詢接口,如果他需要那種統一查詢也可以來查。

1. 推流端實現方案

這是推流端的實現,推流端設計的原則總結下來就是自適應,推流誰都可以做,開源的也很多。但是爲什麼有的做得好,有的做得不好呢?就是看自適應做的好不好。

總結下來有三點自適應,一個是幀率和碼率自適應,這是大家都能想到的。我推流,如果網絡卡了,我就降點幀率或者降一點碼率,把這個事情做好,把流能正常推上去,不要卡頓。也是這張圖裏畫到的,在發送網絡的時候,我們做了一個QS模塊,我們團隊除了做工程化的人之外,還會有四五個博士專門做算法的。

在這裏就有一些體現,我們在碼率自適應的時候,是直接可以回饋給編碼器的,讓編碼器動態調整自己的碼率,儘量保證質量無損,傳出來的視頻碼率下降,視頻平滑。幀率的控制就比較簡單了,當我們發現網絡卡頓了,我們就會反饋給幀率控制模塊。

在採集的時候做一些丟棄的操作,目的就是把我們發送的帶寬降下來。這個我們是基於TCP做的,肯定沒有UDP的效果好,UDP是我們下一步的嘗試,現在還沒有開始。因爲UDP還涉及到源站的一些架構重構,我們還沒有來得及做,現在基於TCP的效果其實已經不錯了。後面除了這種簡單的自適應之外,我們還加了一個算法類的,那個效果就會更明顯。

第二種自適應是軟硬自適應,這個很好理解,像硬件編碼的優點就是手機不燙,缺點一大堆,用MediaRecorder的話,音視頻很難同步,用MediaCodec的話,版本兼容有問題,現在還不太好普及。用軟編的話碼率低,畫質好,除了CPU特別燙,別的都是優點。

怎麼能把這兩個結合起來?我們現在在做的一些策略性的東西,這個就是個體力活,就我們在自己這邊來配置黑白名單,有一些Top50到Top100的高端機型我們用人來測,性能沒有問題的話,我們就上軟編。因爲剛纔也聽到了軟編都是優點,除了燙。

熱門機型有一些低端的,軟編受不了的就改成硬編。因爲硬編是體力工作,所以適配的機型肯定是有限的,沒有誰敢保證能夠全平臺、全機型適配硬編,所以下面的一些非熱門機型,我們來不及適配就軟編。這樣做下來的話,基本能達到99%以上的適配率。在一些大用戶那邊已經驗證過了這個數據。

第三個自適應,算法自適應。我們是真正的第一家能夠把h.265做成商業化的公司。現在所有的都在提h.265,不知道大家對h.265了不瞭解,有沒有人聽說過h.265可以商業化在Web端無插件播放?我們現在做到了在賽揚機器上可以播30FPS的720P視頻,在瀏覽器上不用裝任何插件,這是我們持續優化的結果。當然這個不適合移動的場景,是我們在接另外一個場景的時候用到的。

在移動端我們做到了IOS手機720P編碼,做到15FPS,然後CPU不會打滿,可能是50%到70%之間。之前數據是打滿一個核。這是因爲我們之前有很多做算法的團隊,最開始是做技術授權,後來想在一些產品上落地,移動直播其實是h.265的一個很好的落地的場景,爲什麼這麼說呢?

推流端的任務是把更好的畫質推上來,網絡有限的情況下,我怎麼能推上來更好的畫質?h.265相對h.264來說能把帶寬省掉30%。30%的概念是在視頻點播類的應用裏能省點錢,在初創應用來說根本就不在乎,因爲主播更貴,誰在乎這樣30%的帶寬。

但是在移動推流就不一樣了,30%是從480P到720P的變化,就是你本來只能推480P上來的畫質,經過h.265這種編碼之後能推上來720P的,主播的需求就是網絡夠好,CPU夠好,我爲什麼不推更好的視頻上去呢?這就是h.265的一個場景,我用算法的優勢,你的機器只要能夠讓我做到用265來自適應,我就可以推上去更好的畫質。

2、分發網絡-多集羣源站設計

分發網絡是躲在很遠的一個地方了,我們當時設計的三個原則就是高併發、高可用、系統解耦,前兩個很虛了,只要是做系統都會想怎麼高併發,怎麼高可用,怎麼橫向擴展最容易。

我們做了一個多源站,相對於很多公司在做單源站的方式,我們就是爲了讓用戶能更好的觸達我們的網絡。在各個集羣、各個城市做了多源站,現在不光是國內有幾個點,在香港和美國我們也各做了一個點。這樣怎麼能做到橫向的擴容和數據與業務中心的隔離,是花了一些心思的。這種方案並不是很難,用一些存儲做好同步其實也做到了。

高可用,就像DNS這種,保證服務單點的,高可用都能做到。怎麼做到系統解耦,因爲傳統的CDN只是負責流媒體的分發,我們相對於它的優勢就是我們除了做流媒體分發以外,還做了很多多媒體的功能,像截圖、錄像、轉碼、多分辨率適配這些東西,這些東西是會影響系統穩定性的。怎麼能在這裏做到真正的解耦,保證系統穩定是下了很多工夫的。

一些開源服務,也做多分辨率適配,但是它所有的轉碼調度都是由它的流媒體服務來調起的。包括轉碼的生命週期也是流媒體服務來控制的,他們都在同級部署。其實這是有很大問題的,多分辨率適配和原畫的推送和分發完全不是一個優先級的服務。做系統定級的時候就應該把它們分離開,應該分離在不同的系統來做。


多集羣源站就是剛纔說到的,儘量用三線機房,或者BPG機房,然後在各個城市南北都布點,儘量的更近的觸達用戶,讓用戶推流更容易。同時我們在每個源站都部署了金山雲的存儲,KS3。

部存儲的目的也是爲了能夠更好的保證用戶截圖和錄像的文件的可靠性,存下來之後我們就不管了,交給KS3,當然KS3多媒體服務也是我們維護的。做轉碼截圖,或者是轉分辨率合併一系列操作,是由另外一套系統來做,我們把這些多媒體的服務和源站的服務做了解耦。

在線轉碼是一個非常耗CPU的業務。一臺現在很高端配置的24核機器,如果我想轉一些畫質比較好的視頻,每個視頻轉三個分辨率,這樣我轉八路就把它打滿了,這是很耗CPU的。如果我轉了沒人看,這個CPU就在那耗着,而且這個是不適合和源站混部的一個服務。

轉碼要和數據離的近,在那個源站集羣的同一機房,我們會申請一些轉碼的資源,然後由核心機房來統一調度。我們把調度和具體的功能分離開,根據你這個流推到哪,我們就就近在哪裏轉碼。轉碼也加了一些實時轉碼的策略。

爲什麼要做在線轉碼?因爲推流端已經是盡最大努力把最好的畫質、最高的帶寬傳上來。但是播放端不一定看得了,這樣我們就需要把它轉出來,而且h.265雖然好,但是有個最大的問題就是在移動端的瀏覽器上沒有辦法播。分享出來的必須是h.264,要不然去微信或者是QQ瀏覽器,你是看不了的。

就是如果我用了很高深的技術手段,把你的h.265的視頻推上來了,畫質很好。但不在我們端上就看不了,你要想分享的話,我們可以幫你轉出一份h.264的來分享。轉碼是一個高CPU佔用的場景,如果我不對CPU做合理的分配的話,很快我的機器資源就會被打滿。

我們做了兩種策略,一種是有限的機器合理調度。我們的轉碼系統是個分佈式,流水線式的,類似Storm那種系統,但是我們自己做得更適合轉碼。任務進來之後,我們第一個流程不是轉,而是分析,看看你是要轉成什麼樣,你是什麼畫質,大概會用什麼CPU。

如果你的CPU佔用很多,我會認爲這是一個很難再次被調度的服務,比如你一下進來一個佔四個核的轉碼服務,後來再來一堆佔一個核的,肯定是一個核的比較好調度,這個機器資源緊張了,我可以給你調度另外一臺機器,或者另外一臺機器本來就有些空餘,現在剩三個核,我接不了四個核的,我只能先接一個核的,所以我們會按優先級,優先分配高CPU佔用的任務,然後纔是低CPU佔用的任務,在流式系統裏,會在預分析之後把不同的任務扔進不同的優先級隊列,這個優先級隊列就承擔着去轉不同分辨率視頻的職能。

而且在後頭如果需要降級容災的話,也是靠這個優先級隊列來解決的,每個用戶會有配額。我剛纔說24和準24路,其實對於一個雲服務公司來說這個量太小了。像我之前在百度做媒體雲的時候,每天轉碼量是有30萬,我覺得一個業務做大了,一天30萬的轉碼量是很正常的。

這是考驗併發的一個項目,怎麼能做到儘量的把CPU打平,因爲波峯波谷很明顯。像h.265這個場景,我們是做了一套實時轉碼,有人分享就立刻給你轉,讓用戶一旦開始分享的時候,能達到秒開的作用。但是你不看的時候,我們會有策略儘快幫你停下來。因爲這種分享出去的視頻並不是一個高併發的業務,有人看我們纔給他轉是個比較合理的場景。

對於那些低分辨率的現在也在逐步上灰度,不是說所有的你分發了,你發起了,我都給你轉,我們會逐漸判斷,有人看我們才轉,儘量節省系統資源。後面也會考慮存儲資源,因爲每個機房都會有存儲,存儲是完全不用CPU的,它保證的是磁盤和IO,和我們完全是資源不復用的,是可以混部的,後面我們會考慮一步一步的混部。

CDN的分發環節,分發環節其實有很多東西是需要播放來配合的,比如說現在推流爲了保證畫質好,我會增加B幀,加大GOP,這樣編碼出來的視頻質量會變好,代價就是我增加了GOP,那我的延遲就會大,用戶一定是從上一個關鍵幀開始看,這樣他看到的可能就是5秒甚至是10秒之前的視頻,這個對社交類的移動直播是不可忍受的。既然有這種需求,源站就需要把之前的都保存好。但是怎麼能讓延時被消化掉,就要靠播放端。

3、播放器端實現方案

這是播放端的實現框圖,中間少畫了一個地方。這就是個傳統的播放器框圖,沒有體現出我們的核心的技術點,數據從網絡接收進來之後,經過RTMP的Demux之後,我們是有一個模塊的,這個模塊會去判斷當前視頻是否需要被丟棄,這個原則也和我們接收緩存有關係,我們緩存配的是兩秒,如果超過兩秒,或者超過某一個其他的閾值的話,我們會開啓丟棄的模式。

這個丟棄有多種策略,有的是直接丟掉幀,有的是快進。如果做過播放器就會知道,傳統的視頻追趕一般都是在視頻解碼之後來做追趕。解碼就意味着會耗CPU,尤其是現在如果我想播720的視頻,光是解碼就基本上勉強實時的話,根本就沒有什麼追趕的餘地了。

所以我們在算法上做了一些優化,我們拿到這個視頻的時候會先去判斷它是不是一個可以丟的,如果它是可以丟的,在解碼之前我們就丟,但是這樣丟會出問題,因爲解碼器會內部不連續,一旦解碼器內部不連續了,它可能會產生黑屏,所以我們即使要丟,也是在解碼器裏邊做了一些定製化的開發,還是把要丟的視頻傳進去,讓它自己來丟,它不去解,這樣就能達到更快速的把這個視頻丟掉,趕上現在的實際主播的進度。

這樣的話,如果我們網絡狀況很好,不擔心以後抖動的話,我們能做到從推流到觀看是2秒的延遲,但是一般我們都控制在4秒,就是爲了防止抖動產生。

剛纔說的是丟的這種邏輯,如果想快進,類似鬥魚那種,在一點進去之後,開始畫面是很快過去的,但是沒有音頻,我們現在在做有音頻的方式,視頻在快進,音頻也在快進,這樣的話聲音會變調,因爲採樣率變了。以前在做端的經驗的時候,也做過這種變速不變調的算法,很多開源的,改改其實效果都能不錯,這種算法只要做好逆向優化,放進來之後,音頻也能保證不變調。

日誌收集,可能日誌收集不是所有的開發者都願意接受的,但是有的開發者是逼着我們要我們做,因爲他們需要這個數據來定位問題,就像我剛纔說的,經常有人會問,是不是又卡了,這個問題被問多了之後,大家都希望知道爲什麼卡,端上的日誌不收集上來是沒有辦法定位出這個問題的。我們現在有日誌收集的策略在用戶同意的情況下,會定期可能幾百條打成一個ZIP包發上來,這個數據是我們和用戶共享的。

播放器其實我們也趟過坑,最開始我們基於VLC做,因爲最開始我們做媒體雲是做點播的業務,VLC是個挺好的架構,但是用VLC做追趕這個邏輯就能把人坑死,特別難改。因爲它裏頭一層一層耦合的很重,即使到最後改完了,聲音也有卡的情況。後來還是用更簡單的框架,自己來寫上層的所有控制。所以在移動端的直播場景和點播場景還是有很大區別的,這也就是爲什麼最近突然又出現了很多在視頻語音業務上的門檻。



這頁我剛纔已經陸陸續續都提到了,就是我們如何來定位問題,如何滿足播放器的兼容,還有追趕的各種體驗,發包的時候,我們會注意APP的大小。因爲我們是一個採集和播放都是由我們提供的端到端的方案,有很多庫是可以複用的,如果都用我們的話,我們可以把其中一些庫做合併,最大程度節省我們提供的壓縮包的大小。

用戶案例

這個是我們實際接的一些用戶的案例,其中有的主推的硬編,有的主推的軟編,很多是產品上的一些細節了。我們也在通過這些案例,分析到底哪些產品適合做社交類的直播,已經看到了有一些有用戶基礎和關注關係的開始有火起來的希望了,而且也是他的需求提的最多,也是最有意願上h.265的。一旦你有了這種關係,真的過了試水試錯這個階段的話,就會非常關注你產生的內容的畫質,由於我們這是端到端的服務,所以非常適合接入這種用戶。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章