內容來源:2017年6月24日,梨享計算前端工程師謝庭在“騰訊Web前端大會 TFC 2017”進行《基於WebRTC的P2P-CND流媒體加速》演講分享。IT大咖說作為獨家視訊合作方,經主辦方和講者審閱授權釋出。
閱讀字數: 4311 用時: 6分鐘
嘉賓演講視訊地址:t.cn/RCIMlWn
PPT地址:t.cn/Rp9hZ7R
WebRTC的誕生背景
在講WebRTC之前,我們先回顧一下Web通訊的演化歷史。在AJAX出現之前,也就是05年之前,如果需要更新內容,必須過載整個網頁頁面。AJAX出現之後,通過在後臺與伺服器進行少量資料交換,AJAX 可以使網頁實現非同步更新。但AJAX不能與伺服器進行雙工通訊,因此伺服器無法主動推訊息給瀏覽器,只能通過瀏覽器進行輪詢。Websocket的出現使這個局面得到改觀,瀏覽器與伺服器能進行全雙工通訊。不管是AJAX還是Websocket,都需要將資料傳送給服務端。為了在兩個使用者間傳送資料,開發者需要購買伺服器網路,這方面的成本是非常龐大的。由谷歌支援的一項新技術——WebRTC徹底改變了這個局面。WebRTC是Web Real-Time Communication的縮寫,實現了瀏覽器之間直接的實時通訊,而不再需要伺服器中轉,谷歌致力於讓其成為HTML5的標準之一,目前大部分瀏覽器也已經支援。
WebRTC與P2P的結合
12年穀歌的chrome瀏覽器正式原生支援WebRTC,web開發者只需要幾行javascript程式碼就可以開發出豐富的實時多媒體應用,而使用者也無需安裝外掛,直接開啟瀏覽器就可以與對方實時聊天。這時候有些嗅覺敏銳的開發者開始利用WebRTC的資料通道技術做P2P流媒體,例如國外一家公司叫做peer5。我們公司的創始人Alan在騰訊工作的時候也投入到這方面的研究,但失望的發現用WebRTC做P2P流媒體還有一些問題難以解決,比如使用者線上的時間並不穩定,當使用者關閉頁面,WebRTC的資料通道也就關閉了。隨後在13年和14年,Firefox和Opera也相繼宣佈支援WebRTC。這時Alan提出一個大膽的設想,既然瀏覽器做種不穩定,那麼把相同的協議實現在路由器和NAS中呢?我們都知道路由器是24小時開啟的,但大部分時間是處於閒置狀態,如果能把這些計算能力和網路頻寬利用起來,這樣相當於千家萬戶都是節點,你的鄰居甚至你自己也許就在為你看視訊提供加速,想想都是很酷的事情!因此我們提出了眾包CDN的概念,並且申請了專利。15年,騰訊的X5瀏覽器核心和微信也提供了支援,同年,我們梨享計算也正式宣佈成立。
可能大家會有疑問,WebRTC將來真的會成為一種主流技術嗎?我們用事實說話,看看各大瀏覽器的支援情況就知道了。從圖中可以看出,大部分瀏覽器都已支援WebRTC,包括chrome、firefox和opera,微軟的edge瀏覽器部分支援WebRTC。另外,蘋果也在近期的WWDC大會上宣佈safari11支援WebRTC。未來基於WebRTC的應用將越來越多,這是可以肯定的。
WebRTC媒體會話原理
我們假設現在有兩個瀏覽器A和B要建立WebRTC對等連線,對等連線就是兩個Web瀏覽器之間的直接媒體連線,如果A要主動聯絡B,需要先通過HTTP向信令伺服器傳送一個SDP,SDP可以理解為一個電腦名片,全稱是Session Description Protocol,會話描述協議,用於描述對等連線的媒體特徵。那麼信令伺服器又是什麼呢?它就像一個紅娘,幫兩個互相不認識的人牽線。瀏覽器A發過來的SDP叫做offer,信令伺服器將其傳給瀏覽器B,後者收到後回應一個SDP物件,叫做answer,也通過信令伺服器中轉給A。交換完SDP後,兩個對等端就開始嘗試ICE打洞,打洞成功後開始協商金鑰,之後就可以開始安全的媒體或資料會話了。
ICE打洞原理
由於IPv4提供的IP資源有限,IPv6還沒有推廣開來,大部分網路裝置還處於內網中,需要通過NAT裝置來與外部internet連線。NAT全稱Network Address Translation,網路地址轉換,裝有NAT軟體的路由器叫做NAT路由器,它至少有一個有效的外部全球IP地址。這樣,所有使用本地地址的主機在和外界通訊時,都要在NAT路由器上將其本地地址轉換成全球IP地址,才能和因特網連線。當兩個對等端處於不同的區域網中時,需要先知道對方的公網IP和埠。這時候可以先向STUN伺服器傳送測試資料包,後者做出響應,指示其在測試資料包中監測到的IP地址,此地址將成為潛在的候選地址返回。拿到候選地址的瀏覽器將其通過信令伺服器傳送給對等端,對等端也進行同樣的操作,之後雙方用所有得到的候選地址嘗試連線,如果都沒有成功的情況下,會用TURN伺服器來作為中轉伺服器,TURN伺服器是在所有替代方案都無效的情況下才有采取的,因為成本比較高昂。為了加速通話建立時間,有一個叫trickle ice的方案,其思想是客戶端一邊收集candidate一邊傳送給對方,比如local candidate 不需要通過stun獲取直接就可以發起,這降低了了連通性檢測完成的時間。
WebRTC資料通道
接下來介紹一個比較重要的概念——WebRTC data channel。我們基於WebRTC來做P2P流媒體,實際上就是用的data channel能力。那麼data channel到底是什麼呢?雖然有關WebRTC的宣傳主要側重於它對於實時音視訊通訊的支援,但設計師一直都希望它也支援實時資料傳輸。相比Websocket和HTTP,資料通道支援流量大、延遲低的連線,具有穩定可靠等優點。而且data channel的介面和websocket一樣,也是通過send來傳送資料,通過ommessage來接收資料。那麼如何對data channel資料傳輸的可靠性進行控制呢?通過剛才所講的dataChannelOptions這個javascript物件,可以讓data channel在UDP或者TCP的優勢之間進行切換,比如讓資料傳輸得更加穩定可靠,或者傳輸得更快。其中有幾個比較重要的欄位:ordered:設定資料的接受是否需要按照傳送時的順序,maxRetransmitTime:設定資料傳送失敗時,多久重新傳送,maxRetransmits:設定資料傳送失敗時,最多重發次數。主要是配置ordered,當設定為true時資料通道表現更像TCP,false時表現更像UDP。
梨享計算與WebRTC
此外,我們公司一直對WebRTC標準化保持著關注並貢獻力量。在去年,我們在研發過程中發現有一個第三方的webrtc協議棧能與chrome瀏覽器進行通訊,但無法與firefox通訊,通過對比SDP發現firefox有一處實現與標準規範不一致。於是我們與firefox開發團隊取得聯絡,提交了我們的修改建議,最初他們認為沒有問題,但最終還是採納了我們的建議,對sdp進行了修改。這也算是我們對推進webrtc標準化做出的一點點貢獻。另外,我們也一直與騰訊瀏覽器核心團隊保持著聯絡,爭取WebRTC技術以及本次分享的上層的P2P-CDN加速協議得到全面的支援。
WebRTC與P2P流媒體
把WebRTC的data channel搞清楚後,我們就可以用用它來做P2P流媒體了。這方面已經有國外大神開發的知名開源專案:WebTorrent,在github上有1萬多顆星。WebTorrent是一個開源的基於WebRTC 和BT協議的js框架,完全用javascript編寫,可以同時執行於 Node.js 和瀏覽器,由於基於WebRTC,因此WebTorrent不需要安裝任何外掛,就可以跑在瀏覽器上。同時支援Chrome, Firefox 和 Opera瀏覽器。但是由於是基於BT協議,所以是一種pull-based的演算法,這種演算法是一種隨機抓取的策略,隨機抓取其它節點的buffer,但這樣會存在一個問題:抓取的buffer不一定是目前需要的,也不一定是其他節點需要的,而且還會浪費下行頻寬和其它節點的上行頻寬,因此同時造成了“頻寬飢餓”和“內容飢餓”問題。下面介紹一種改進版的pull-based演算法——FirstAid演算法。FirstAid是基於視窗滑動的,每隔一段時間觸發一次視窗滑動,每個視窗又可以分成三段:urgent、normal和prefetch,urgent顧名思義,是離播放時間最近的buffer,所以優先順序別最高,normal和prefetch優先順序遞減。當父節點為子節點傳輸buffer時,會優先滿足urgent級別的要求,而暫停normal級別的,所以最緊迫的需求會優先得到滿足,當子節點的urgent需求得到滿足後,需要回過頭來彌補他的競爭對手的需求,以達到一種互惠互利的狀態。和剛才pull-based演算法思想截然相反的是push-based演算法,其中比較有代表性的是FashMesh演算法,由港科大的學者提出來的一種P2P演算法。FashMesh是基於一種叫Streaming Mesh的演算法,將源節點的資料流分成多個子流,通過多棵生成樹構成mesh來源源不斷的傳輸給子節點,這種演算法的優勢是延遲低,頻寬利用率高。Fast Mesh還可以根據每個子節點的上行頻寬來動態的調整網路拓撲結構,讓上行頻寬大的節點更加接近源節點,從而充分利用網路的現有能力。根據一項對比試驗,FastMesh可能是目前眾多P2P演算法中效果最好的。但這個演算法也有缺點,當節點進入或離開網路時,都需要重新調整拓撲結構,因此不適合節點變化較大的情況。
我們自行研發的演算法——Push-Pull演算法則綜合了push-based和pull-based兩種演算法的優勢,用pull的方式從父節點獲取優先順序最高的buffer,由父節點以push的方式為其提供後續的buffer。另外,我們的演算法混合HTTP、HTTPS、WebRTC、Websocket等多種協議,在優先保證使用者體驗的前提下最大化P2P率。經過測試,Push-Pull演算法具備低延遲、高頻寬利用率、高P2P率、對網路拓撲結構變化魯棒性強等優勢。
PearPlayer
PearPlayer(梨享播放器,github地址:https://github.com/PearInc/PearPlayer.js) 是完全用JavaScript寫的開源HTML5流媒體播放框架,實現了融合HTTP(包含HTTPS、HTTP2)、WebRTC的多協議、多源、低延遲、高頻寬利用率的無外掛Web端流媒體加速能力。基於H5的MSE技術(Media Source Extension)將來自多個源節點的Buffer分塊餵給播放器,再加上精心設計的演算法來達到最優的排程策略及對各種異常情況的處理,Pear Player能在保證使用者流暢視訊體驗的前提下最大化P2P率。
整合我們的PearPlayer.js也非常簡單,只需要短短几行程式碼,把我們的js檔案引入到script標籤中,並把video的id還有token作為引數傳給我們提供的函式中即可。Demo演示地址:qq.webrtc.win/watch,以下是demo截圖。
除了播放器外,我們還開發了支援多協議、多源、混合P2P-CDN的下載器PearDownloader,可用於高清圖、壓縮包、軟體釋出或升級包、音樂、文件等大檔案下載或線上服務的場景(github地址:github.com/PearInc/Pea…),Demo演示地址:qq.webrtc.win/download。
霧計算
最後,講一下霧計算有關的內容。霧計算與雲端計算有什麼區別呢?雲在天空飄浮,高高在上,遙不可及;資料中心距離終端使用者較遠,使用者訊息需要經過若干跳才能夠到達。而霧是貼近地面的雲,是現實可及,就在你我身邊。霧計算並非由效能強大的伺服器組成,而是由效能較弱、更為分散但離使用者更近的各類計算裝置組成,例如智慧路由器、網路儲存裝置等。霧能夠彌補雲的不足,並和雲相互配合,協同工作。我們Pear公司一直在踐行霧計算的理念,通過與國內知名的路由器、NAS廠商合作,我們擁有海量可持續穩定提供服務的節點。大部分頻寬、儲存、計算資源通過眾包方式收集自終端使用者穩定線上的邊緣裝置,服務能力覆蓋全部地域、所有運營商、每處網路邊緣。我們自研的排程系統可以動態、實時的感知和排程,讓資料傳輸距離儘可能接近“零跳”。
相對於傳統的模式,我們可以說是站在共享經濟的風口上。我們知道傳統的CDN廠商會先以批發價從ISP買進頻寬,然後再以零售價賣給CP,CP買入頻寬後進行內容分發,為終端使用者提供CDN服務。我們與硬體廠商合作,在其裝置中植入我們的軟體,從而在千家萬戶擁有了分佈廣泛的節點。CP廠商和傳統CDN廠商從我們這裡買入頻寬,我們將其內容分發到各個節點中,持有裝置的使用者在提高其計算資源和頻寬資源的同時,也會得到我們的返利,BGP機房、ISP骨幹網的壓力也得以緩解,從而實現多贏局面。