版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/81278773
本文來自百家雲技術總監張弩在LiveVideoStackCon 2017大會上的分享,并由LiveVideoStack整理而成。張弩分别從伺服器端與架構端介紹了百家雲的整體結構演進,并對未來行業的發展方向進行了分析、展望。
文 / 張弩
整理 / LiveVideoStack
本次的分享内容可以分為四個部分。第一部分是簡介,幫助大家了解一下百家雲這家公司以及它的産品情況。第二和第三部分将分别從伺服器端和用戶端來描述整體結構的演進。最後會站在百家雲的角度來分析一下整個行業未來發展的方向。
1. 簡介
1.1 公司背景&平台簡介
百家互聯,是一家線上教育公司,成立于2014年,它旗下有個品牌叫跟誰學。百家雲團隊原來主要是在跟誰學這個平台上面做一個音視訊的教育工具,随着業務和技術的發展,逐漸的穩定并且有了一定的品質保障以後,就考慮是不是可以給一些其它的機構,或者第三方的行業提供一些解決方案,我們在原來的研發基礎上,提供了SAAS層的服務,就逐漸演化出了百家雲這家公司。當然以後的百家雲會更加獨立的為這些行業,或者說教育行業的一些客戶去提供服務,總之百家雲可能會提供一些音視訊的整體的解決方案給大家。
1.2 個人簡介
我畢業于西安電子科技大學。在視訊會議公司工作超過了七年,負責軟體視訊會議系統設計、開發。2012年我進入了91外教當研發總監。2014年加入了跟誰學,主要負責線上教育系統的開發,直到百家雲成立後任技術總監。
1.3 線上教學系統的基本業務需求
如果我們能夠實作了以上的功能,滿足了基本的業務需求,那麼作為一個線上教育的産品就比較完善了,能夠提供出标準的一些服務了。
1.4 特色功能
百家雲在教育行業領域深耕了多年,以上是一些簡單的、有特色的功能。首先整個産品是全終端覆寫的,或者說主流的一些終端都會有覆寫。例如Windows、MAC、IOS、安卓,包括微信場景,PC和手機的浏覽器,這些場景下應該都是全終端覆寫的。當然還有對于應用形态或者業内形态來說,大班課、小班課、一對一、雙師、展會直播都是有比較好的覆寫。第三個特點就是我們在移動教學場景下實作了多路音視訊互動的,這對于教學場景來說也是一個新的探索。第四個特點就是我們實作了動态PPT全終端支援,因為動态PPT是能夠比較好地還原老師授課内容的一個特别好的功能。第五個特點是雲端錄制的多路音視訊支援,我們能夠把多路音視訊都錄下來,在學生終端進行複習的時候來回看。另外随着海外教學的不斷深入,業内這塊的發展也非常好,我們對于全球資料節點的部署和海外專線優化也做了很多工作。當然對于視訊會議來說,還會有基本的能力,即私有化部署能力,但是對于雲平台來說,為了能夠提供出私有化部署的能力也做了很多的努力。
1.5 界面展示
從上面可以看到我們一個基本的界面展示。最上面一排是PC端的一個基本的界面,下面一排是手機端APP的一個橫闆和豎闆的界面。其中非常經典的界面就是左上角那個界面,它的左邊是我們的白闆區,右邊是我們的視訊區。當有多路視訊時,視訊區就會進行一個排列。
2. 伺服器端結構演化
2.1 信令伺服器
1) 初期單伺服器模式
首先,對于信令伺服器整個的演變,我們最早是要做一款線上的教學産品,也參考了當時已有的一些系統,規劃了關于信令伺服器的一個簡單的業務模型。我們在最底層采用TCP的網絡連接配接;從協定層來看,我們有HTTP的一些接口,當然我們最核心的是用WebSocket做一個應用層的開發;對于邏輯部分,也就是房間的管理、連接配接的管理部分。另外還有白闆、聊天、以及音視訊管理的一些子產品;在接口層我們提供一些接口友善使用者做一些接口的操作。對于整套系統來說,特點就是”單伺服器”,很快就可以上線,但是它的問題也很多,比如負載、安全、内部結構,業務耦合,接下來我們提出了一些解決方案。
2) 拆分獨立服務
我們很快就進行了伺服器的更新并有了一個整體的思路就是提升系統的負載、擴大使用者的覆寫面、優化單伺服器中部分子產品的性能問題。在最底層我們對一次登陸子產品進行了拆分。登陸子產品拆分出來以後主要承擔了所有使用者的統一登陸、身份校驗以及簡單的負載均衡職責。另外我們有大量的Agent代理子產品,這些子產品主要解決使用者的覆寫和端口的問題。我們在代理這一層做了各種端口的映射,讓使用者能夠無縫的連上。對于性能這塊,我們發現聊天伺服器有很嚴重的性能問題,是以我們也單獨對聊天伺服器做了一些優化。
3) 聊天伺服器思路
也許大家會覺得聊天是一個比較簡單的、正常的業務,不會有什麼性能問題,但是如果我們集中在一個特别大的聊天室内,每個使用者的互相聊天互相都要被看到的話,整個帶寬産生的資料量很大。如果使用者的帶寬不夠大,那麼文字聊天就會非常嚴重的影響到整個音視訊流的穩定性。是以我們對于整個聊天的業務按照一個四象限法則的方法進行分析,我們認為有一些消息是可以被适當的選擇丢棄的,這樣可以非常明顯的降低我們整個聊天伺服器的系統負擔,我們按照這個思路對聊天伺服器的整個結構做了一些改動。
首先我們在最底層按照房間進行調控,對于房間裡面,我們會把不同的使用者分成組進行調控。每一個組裡面的消息的隊列,根據重要性可以進行選擇丢棄。我們也會對一些重要的、非實時的消息專門做一種隊列,當使用者的負載不高的時候,我們實時的把這些消息推送給使用者。
有了這套改動以後,我們整個聊天伺服器的穩定性和使用者的體驗并沒有受到非常大的影響,而且重要的消息依然是有效的傳遞給了使用者。但是我們核心伺服器的單點問題依然很明顯,它的解耦性還沒有完全的解開,房間伺服器的負載也沒有很好的解決。下面我們又對房間伺服器進行了一次拆分。
4) 拆分房間伺服器
我們這次拆分的重點是把房間伺服器的單點變成多點,并且每個點可擴充,根據使用者的負載線上上進行随時增減伺服器。第二個就是我們根據信令流的一些特點,把伺服器分成幾個子產品。首先我們有廣播代理子產品,這個子產品主要是為了去接受使用者的連接配接,并且處理第一道的消息信令;第二個就是我們中間有一層叫做消息路由的子產品,這個子產品主要是将收到所有的信令,根據信令的不同要麼做轉發,要麼交給後面的一些子產品去處理。後面兩塊是使用者資訊的管理和房間資訊的管理,這兩塊主要是資訊的記錄和儲存以及持久化的工作。是以基于這一套模型,我們支援各自子產品能夠線上上随時的根據負載情況進行部署,而且我們的任何一個消息,根據不同的類型能夠在消息裡面進行流轉,例如使用者查找、雷射筆等消息信令的處理利用這套模型就會非常的高效。
5) 接入層優化
接下來就是我們接入層的優化。對于SLB子產品,它主要是解決了我們單點覆寫的問題,并且大量的減少了我們自己部署Agent代理的數量。在SLB後面我們自己搭了一層Nginx分發的業務,這部分的業務主要是為了我們的核心業務做一些負載平衡。比如我們不會把所有的使用者分到一套伺服器節點上,而是均勻的分散在不同的伺服器節點。一旦中間後端有一個伺服器有問題,也不會影響到整個房間内的所有使用者。另外,我們在Agent這一層有大量的連接配接日志的系統,而且我們還有對于各種協定、業務線的一些分離,這些都是由Agent的方式來解決。當然SLB還有一個比較重要的一點,那就是它能為我們提供比較好的防火牆的功能。
6) HTTPS、WSS支援
我們在後期對信令伺服器也做了一些HTTPS和WebSoketS的支援。但是這個也會給我們帶來一些問題,是以我們并不會把整個系統全量的支援HTTPS,我們隻是對最外層的接口層進行HTTPS的支援,對于系統内部,我們還是用各種協定進行高效的保障。對于整個系統來說,雖然支援HTTPS或者WebSockets,但是對于整個系統的影響沒有那麼大。是以經過之前的所有的優化以後,我們做了一個完整的信令伺服器的結構圖。
首先對于使用者來說,通過域名解析的方法連到具有均衡負載的SLB接口層,再通過後期的分發連接配接到廣播代理層。如果有些信令是需要被持久化,或者被記錄,我們就分發到使用者管理或者房間管理子產品。Redis在持久化的這部分承擔了很重要的職責。最後,Sinker這部分是對于一些外部的系統或者内部的系統提供一些接口層的支援,包括各種系統之間互相消息的轉發,或者觸發性的事件。
2.2 媒體伺服器
1) 初級伺服器模型
我們下面說一下媒體的部分,對于音視訊資料轉發的這部分伺服器的演化。首先,我們參考了當時已有的直播系統并快速搭了這一套系統結構,但是我們後來發現我們教學的整個業務和這種秀場類的業務是有很大的差別的。首先我們的房間數很多,我們在初期就有幾千節課或者上千節課,這就相當于有一千多個主播了,但是對于一個秀場類型的話,一千多個主播已經是挺多的,然而對于教學來說,一千多個教室才是剛起步,但是每個教室裡面的人又非常的少或者大部分情況都很少。這種情況下就造成了大量的資源浪費,并且造成了中心伺服器節點的壓力的巨增。是以,對于教學系統來說,采用一個傳統的直播模型是不太合适的。于是我們為了節省資源,便做了一個平級互推的方案。
從上面結構圖可以看到資料流是沒有任何浪費的,任何一個推流的使用者都會把自己的資料流推給它就近的一個媒體伺服器,拉流的使用者就會從它就近的一個媒體伺服器上去拉流,互相之間把資料落下來。但是帶來的問題卻很嚴重,首先,拉流的伺服器是要知道推流伺服器的具體資訊的,用戶端要把資訊要帶到媒體伺服器上,是以整個伺服器和用戶端的解耦又是很嚴重的問題。第二,對于伺服器的流控就變得很複雜,因為任何一個媒體伺服器,它往外面轉發的時候,不知道轉給的是一個戶,還是另外一個伺服器,如果是另外一個伺服器,那個伺服器上還挂了好幾千學生,對于流控來說,我們就變得極其的複雜。第三,因為它是一個平級結構,任何媒體伺服器之間,都會互相進行傳遞資料,對于這些兩點之間,或者兩個媒體伺服器之間的這個網絡狀況就非常的不穩定,假如說其中任何一個媒體伺服器之間有網絡的波動,都會影響到這堂課裡面的其他使用者,是以運維的難度也變得極其的大,我們很難找出在整個伺服器機群内部,所有的伺服器之間都能夠無縫的很好的傳遞資料,當然最後的話就是資料路由太簡單了,因為就是個平級的,就是一級轉發的一個結構,更複雜的一些環境很難适應的是以,我們根據教學場景做了一個兩級伺服器結構的調整。
2) 互動直播模型
對于兩級的結構,我們有一層推流的伺服器和一層拉流的伺服器,推流使用者會把自己的流推送給推流伺服器,拉流使用者從拉流伺服器上拉流。這種結構的調整讓單教室的使用者容量能夠達到100萬路,這已經遠遠滿足我們一個單教室使用者的極限了。而且,對于各個伺服器上的流控變得非常簡單。另外,運維工作也減少了,特别是對于我們的大量的一對一業務來說,降低了最少幾十毫秒的網絡延遲。我們使用了這套互動模型以後,到目前為止支撐我們的業務和整個的擴充都沒有太大的問題。
3) CDN支援的演變
前面介紹的是我們自己的媒體伺服器,另外我們還有對CDN的一些使用。一開始我們是自建RTMP、HLS伺服器,因為我們是一個全終端的使用者,無論在微信這一端,還是浏覽器這一端,大量的現在還在使用RTMP或者HLS這種基于TCP的協定。但是随着CDN這塊業務越來越穩定、體驗越來越好,我們也使用了CDN,從剛開始選擇一家CDN由于覆寫上有問題,到後來我們就選擇了多家,但是這又造成了多家互推責任,導緻問題解決不了。後來我們又發現這其中還有很大的問題,就是各家CDN對于資料和編碼的支援力度也不太一樣。是以我們就不太再依賴于CDN做類似于轉碼這種事情,我們隻依賴于它做分發,而且不做這種多家的互相的分發,而是由統一的伺服器做完所有的資料處理以後,直接推送給多家CDN,由多家CDN去完成覆寫的動作和轉發的動作。我們對于CDN這塊的支援,就逐漸演化成這個樣子,而且從我們現在情況看起來,CDN的廠商的支援效果也越來越好。
4) 海外線路支援
對于海外線路支援這塊,我們也做了很多工作。另外對于這一塊的擴容和災備就比較簡單了。我們可以根據使用者規模和特點實作實體隔離伺服器資源,或者不同實體機房進行互相備份。
3. 用戶端疊代
1) 用戶端初期
前面介紹的主要是伺服器端的這塊,我們下面就介紹一下用戶端這一塊。用戶端一開始被設定為全終端支援,經過一定的技術選型,我們決定使用Chrome這一套架構。初期的用戶端具有一些基本的功能,後期我們對它也進行了擴充。
2) 擴充基礎功能
上圖是我們全終端的一個結構示意圖。最下面的Html5 UI這一層開發之後,我們在Windows Web、PC Web或者移動端的Web上的一整套UI就全搞定了。這一層依賴于Chrome的中間件與上層打交道。在功能這一層我們提供了音視訊的一些基本的子產品。對于最上面的協定層,我們是基于UDP或者TCP進行音視訊的傳輸。在HLS和RTMP這個子產品進行編解碼,然後發送給我們的CDN的叢集。Web Socket協定子產品主要指的是信令子產品,在這層我們還提供了混音功能,由于伺服器端進行混音的代價很高,是以我們在用戶端實作混音。這個好處就是對整個卡頓的控制和業務的簡潔度都有很大的提升。另外第三方推流是我們一些特殊的功能,我們能夠把推出的RTMP的資料流接收到系統内,再由系統把它分發出去,比如展會直播這種場景用的比較多。
3) APP端
在APP這一端實作了基本功能以後,我們發現了一個比較嚴重的問題,就是用H5在上層做了這套業務以後,它的整個體驗和原聲Native的體驗差别比較大,是以我們也做了一層Native的UI。當然對APP端很嚴重的問題就是它的音視訊調優的功能。
4) 性能優化
上圖是我們對性能方面做的一些簡單的介紹。在我們看來最重要的有三個方面。一個是低延時和少卡頓,解決的方案例如有用戶端Buffer的控制。VOIP音頻編碼特指的是在互動場景下,我們會選用編碼和解碼時間更短的一些音頻編碼,比如WebRTC用的FEC。傳輸編碼這塊,我們特指的是在TCP和UDP之間做選擇。TCP最重要的問題就是TCP發生了擁堵以後,它的整個資料恢複的能力是有些慢的。我們可以通過TCP調優,或者把整個的發送重傳機制做調優,但是對于用戶端來說我們是沒法調的,我們隻能在伺服器端做一些優化。對于用戶端來說也沒有什麼好辦法,是以對于互動場景下,我們主推的還是用UDP的方式。對于丢包重傳,從UDP角度來說,所有的資料包都是不可靠到達的,這些包丢了以後,整個音頻的體驗就會受到很大影響。是以不同的重傳政策對于應用來說就有很大的影響。在我們内部,針對于不同檔位的丢包都有不同的重傳的政策:重傳一次,重傳多次,在一個RTT的周期範圍内,是否要再多重傳一次,這都有一些特殊的一些考量,包括FEC的應用。
還有很重要的一塊就是音視訊體驗裡面有雜音、回音、嘯叫。在我們看來PC上表現可能略微好一些,但在安卓上的體驗更差。我們進行适配了很多不同的安卓的機型,包括聲音的采樣率,整個頻譜高了以後,回音的處理确實是要差很多的。是以我們在互動場景下選擇的音頻編碼的采樣可能也會比較低。對于硬體手機這塊,硬體本身的降噪、混音一緻、自動增益都有一些展現。在這一部分,因為我們的使用者的數量還不能夠達到像QQ,或者其他廠商這麼高,是以我們的适配的數量也不會有他們這麼多。上述兩項我們并沒有一個最終的結論性的東西,是以我們也在不斷的前進和摸索過程中。
最後就是多線程的編解碼和硬體的編解碼。我們發現我們一個雙師的業務,針對于不同的硬體,我們能夠在異地兩個多媒體教室之間,通過1080P的視訊資料能夠很好的還原一個上課場景。這種場景下對于視訊的清晰度的要求和實時性的要求就會很高,是以在這塊編碼的效率就要提升很多。但是我們上了硬體編解碼以後,對于編解碼階段來說其實沒有提升那麼多。在後續的所有的拉伸的處理上,還有整個資料的分發上都會有些特殊的考量在裡面。
在用戶端疊代這個階段我們認為最重要一點就是我們會提供更多的SAAS、SDK、API的支援。我們希望我們的産品能夠應用到不同的教育機構或者不同的行業當中去。對于API這塊,主要是一些賬号、房間管理、基礎資料的查詢工作。
4. 未來優化方向
最後我們談一下在百家雲的場景下,未來有哪些東西是更加重要的。首先就是在浏覽器的場景下能夠對H5 WebRTC的支援;第二點就是在編碼層能夠進行高清的編碼,然後在伺服器端就能夠提供多種碼流的支援,使用者可以通過自己的帶寬情況适配不同的碼流來進行拉流的動作;第三點就是伺服器端需要做一些混頻和混音的服務,這樣就會使整個系統的消耗減少很多;第四點就是對高分辨率的支援,因為未來對于高清碼流的需求會越來越大;最後一點就是未來我們會開發更多的基于教學的課堂行為分析,比如通過視訊人臉識别技術就能夠準确的反映課堂裡學生聽課和老師講課是否專心的情況。