B 站 QUIC 實踐之路
QUIC協議快速建立連線、擁塞控制靈活、多路複用等特性為網路傳輸帶來了不少收益,也更好的提升了使用者的體驗。嗶哩嗶哩高階工程師 王盛在LiveVideoStack線上交流分享中介紹了B站在QIUC研發與部署中的實踐經驗,LiveVideoStack對分享內容進行了整理。
文 / 王盛
整理 / LiveVideoStack
直播回放
https://www.baijiayun.com/web/playback/index?classid=19010981268177&token=-tkUdxVX8Ti1r0cPh106AvZXQLOzrJs4N_7hHIksFNZBJ7OhUy3qsJbeBQgjkUbzjAk6Qj2pOAo
大家好,我是來自Bilibili的王盛,五年多來我一直從事網路協議和點直播系統的研發工作,加入B站後主要負責Bilibili的點直播系統開發,可以說見證了B站的點直播系統從零發展到目前TB級別的整個過程。接下來我將從以下四個方面為大家分享B站在QUIC協議上的技術探索,希望大家能通過此次分享瞭解更多QUIC特性與服務端架構技術細節。
1. 從Http1.1、Http2到QUIC
我們討論QUIC協議一定先從HTTP協議出發。作為目前網際網路上被使用最多的網路協議,HTTP經歷了從1996年誕生到現在二十多年的發展,相對於早期的1.0、1.1版本,現在的2.0版本可以說發生了非常大的變化。據第三方機構統計,2015年HTTP/2版本的更新不僅加入瞭如二進位制協議、多路複用、服務端推送等諸多新特性,更是實現了相對於HTTP/1近兩倍的效能提升。
而我們今天討論的QUIC協議其實就是所謂的HTTP/3,Google從提出QUIC協議以來一直想將其作為優化與替代現行HTTP協議的解決方案。從上圖我們可以看出QUIC是完全基於UDP協議實現的,我們知道現在主流的兩大網際網路傳輸協議是TCP與UDP,前者連線可靠的資料傳輸而後者連線不可靠的資料傳輸;如果QUIC協議建立在UDP協議之上就需要實現一系列與TCP相似的資料傳輸操作如擁塞控制、資料重傳、資料排序等,使得基於UDP的QUIC成為一種使用者態的協議。目前TCP協議實現大部分功能都離不開核心,這就導致如果開發者希望修改調整TCP協議中的某一些特性與功能或根據需求進行定製化開發部署的難度非常大,尤其是涉及到核心改動的工作會帶來不必要的開發成本;除了具備使用者態協議的優勢,為了實現更快的資料傳輸,QUIC也囊括了一些類似於TLS安全傳輸層的功能,為了提高相容性QUIC也提供與之前HTTP2一樣HTTP語義,從而實現在應用層程式方面良好的相容性。
QUIC協議從誕生至今獲得了不少廠家與企業的支援,也為這些企業帶來了收益與回報。縱覽整個行業,國外如Google搜尋、YouTube視訊、Akamai CDN等等都實現了對QUIC協議的支援,國內如騰訊雲的負載閘道器、QQ空間、七牛直播雲的直播推流等都在QUIC協議的幫助下實現瞭如0卡頓的直播推流等等技術提升,而B站的點直播CDN也實現了對QUIC的全面支援。QUIC為這些企業帶來的收益同樣不容小覷,如為Google搜尋頁面帶來了5%的載入速度提升,使YouTube的視訊卡頓率降低了30%;為QQ空間帶來了10%的載入速度提升,幫助B站提升10%視訊首幀的同時減小5%的卡頓,可以說極大提升了網際網路產品的使用者體驗。
接下來我們將QUIC和TCP之間的效能與引數差異落實在使用者體驗層面,首先模擬使用者同時使用分別基於QUIC與TCP的兩個播放器播放同一個視訊檔案,理想環境下使用者的直觀感受是二者畫面基本同步流暢;但如果使用網路模擬工具為使用者播放器端到視訊伺服器端之間的網路傳輸增加20%的丟包,此時基於TCP傳輸協議的播放器會出現明顯示卡頓而基於QUIC傳輸協議的播放器則仍可保持較為流暢的播放狀態,二者會出現5~10s的播放時間差,不難發現QUIC在弱網環境下的傳輸效能優勢非常明顯。
其次我們模擬增加每個資料包的延遲如增加到200ms,隨後使兩個播放器從同一幀開始播放,不難觀察到基於TCP協議播放器的畫面明顯滯後,QUIC的首幀展示也更快。
2. QUIC協議特性
無論是弱網環境的卡頓還是首幀展示,QUIC相對於TCP的實際傳輸效能提升都十分明顯。這與QUIC協議本身的一些特性緊密相關,主要包含以下四部分:
2.1 極短的建連時間
在QUIC的建連時間中大部分為0-ORTT,極少部分是1-RTT,如何實現這樣的分配?首先大家知道,TCP的一個建連包含三次握手,而如果基於HTTPS加密則還需包含TLS一層的一個握手,同時增加1 RTT的時間;綜合來看,已完成建連的TCP連線進行握手大概需要2 RTT,而首次建連的TCP則需3 RTT,其中便包括TLS的證書交換。但對於QUIC協議,若客戶端之前未建連,其第一次建連時需在客戶端直接生成證書與和協議棧相關的配置且附帶一個ID,這些資料會與請求資料一起直接傳送並儲存在服務端,假若服務端已存在以上資料那麼系統會直接進行校驗操作並直接回複數據;而已建連的客戶端則僅需0-RTTs時間,初次建連的QUIC服務端為便於進行建連與校驗會把ID儲存在服務端本地,待服務端完成校驗即可傳送證書至客戶端並進行客戶端校驗,校驗成功即可直接啟動數字交換;且對於第一次建連的QUIC而言只需1 RTT就可完成建連並允許後續的資料互動,以上就是QUIC的建連時間特性——大部分0-RTT、極少部分1-RTT。
2.2 多路複用
QUIC協議的第二條特性為完全多路複用,以HTTP1.1為例,每條資料流基於一個TCP連線,每個TCP連線都單獨傳輸資料,但此TCP連線方案會明顯增加服務端與客戶端的併發負載;HTTP/2對此問題進行了有效優化也就是採用多路複用的傳輸策略,通過一條TCP連線傳輸多路資料,但此方案容易造成隊首阻塞問題:以上圖展示的HTTP/2資料流為例,若Stream 2丟失那麼Stream 1與Stream 3都會被阻塞,直到丟失的Stream 2資料重傳完成之後Stream 1與Stream 3才能被繼續傳輸,這種因為一條資料流的丟失重傳等問題造成其他多條資料流阻塞的現象被稱為隊首阻塞問題;QUIC對此問題進行了修正,也就是把每個重傳過程安排在每條Stream中單獨完成,由於Stream本質上是一個基於UDP的小資料包,所以這種方案並不會造成隊首阻塞問題。
2.3 靈活的擁塞控制
QUIC的第三個特性被稱為靈活的擁塞控制,QUIC能夠在作業系統層面實現完全使用者態得益於協議棧非常靈活的擁塞控制。如我們之前熟知的被用於TCP的BBR擁塞控制演算法也是一開始在QUIC上實驗成功之後才被移植到TCP核心中。當然這種將模組移植進核心的嘗試是一個非常漫長的過程,但為了實現較為良好的擁塞控制並達到使用者態要求,此方案不失為一種良策。
2.4 連線轉移
QUIC的最後一個特性被稱為連線轉移。什麼是連線轉移?假設當你正在家中使用WLAN觀看視訊時需要外出辦事,當你走出家門時手機也會從通過WLAN下載資料改為通過蜂窩網路下載,在WLAN與蜂窩網路切換的瞬間TCP連線會被切斷再重連,這是因為TCP採用包括原IP、目標IP、原埠、目標埠在內的四元組方式表徵一個連線;QUIC並未採用四元組的表徵方式,而是將資料包中一個64位的數值ID作為表徵,無論WLAN與蜂窩網路如何切換,只要傳送至的服務端資料當中的ConnectionID一致,服務端就會預設其為同一個連線,從而避免出現切斷重連的過程。
3. 視訊雲的QUIC實踐
3.1 Roadmap
接下來我將重點介紹B站開發QUIC協議的實踐經驗。我們在開發QUIC協議之前,遇到了以下兩個難點:首先,作為一個正在開發中的協議草案,QUIC協議標準本身需要頻繁進行迭代更新,大約1.5個月更新一個版本。如現在被廣泛使用的QUIC43就是不到一年前從QUIC37、35或39等版本迭代而來,而不斷跟進此協議標準的迭代升級確實是一件很難的事情;其次是開發QUIC網路協議本身是一個比較底層的實踐,需要開發者具備較強的技術素養才能攻克其中諸多的技術難點。B站已在服務端全面上線QUIC,客戶端的QUIC也正在灰度上線中。
3.2 技術選型
我們嘗試探索多元化技術選型,通過一個季度的調研確定了以下幾個可實現QUIC的常見開源專案:Libquic、Caddy&Quic-Go、Stellite&Isquic與Chromium。我們嘗試藉助這幾個開源專案快速搭建並上線QUIC服務端,並仔細對比這幾個方案的利弊:Libquic雖然具有一些可在Chromium中實現的優勢,但其早在兩年前就已經停止更新;Caddy&Quic-Go作為使用(……long)實現的單協議棧,其測試效能無法滿足我們的上線標準;Stellite&Isquic作為商業解決方案不但需要我們花大量成本進行部署,而且其協議棧的功能也不夠全面;Chromium作為Google官方的開源專案,雖然與QUIC協議標準始終保持一致的版本更新,但其接近兩千多萬行的龐大程式碼量明顯增加了我們的運維壓力。基於以上調研結果,最終我們決定使用Chromium快速搭建QUIC服務端,主要分為以下兩步:首先使用Chromium的QUIC協議棧模組打包一些API,其次是自主實現能夠滿足生產環境的UDP Server,結合以上兩者完成QUIC服務端的上線開發。
上圖展示的就是我們在調研與探索過程中參考的資料來源。
3.3 初期架構
上圖展示了B站在QUIC服務端實現的一個初期架構,為了與B站目前點直播系統的(NGX)體系相容,我們僅將QUIC服務端作為一個代理接收來自公網的資料並轉發至本機的(NGX )伺服器。由上圖架構不難發現我們的工作重點是根據在主執行緒上進行收發的UDP資料包中的一些連線,將ConnectID分發至不同的工作執行緒。每個工作執行緒上都會執行一個QUIC協議棧,從而進一步發掘整個QUIC伺服器的效能。需要注意的是,非單一的QUIC協議棧在處理網路UDP資料包或QUIC資料包時存在限制條件,也就是必須按照其ConnectID進行分發,否則就會出現一個連線進入兩個協議棧的錯誤,繼而導致資料丟失甚至服務宕機的狀況。在此限制條件下此架構可實現如負載均衡等功能。與此同時我們通過QUIC到TCP的代理轉發,把QUIC的HTTP2的協議轉發為(NGX) Server使其能夠為本地的(NGX) Server服務並接收(NGX) Server的回覆,最終將(回覆)轉化為UDP包返回至QUIC客戶端,這便是我們QUIC服務端的初期架構與細節。
3.4 使用方式
使用者可直接使用核心支援QUIC的Web端如Chrome、QQ瀏覽器、Opera(核心)觀看B站的視訊;與此同時我們也會盡快灰度上線移動端的QUIC灰,為大家帶來酣暢淋漓的QUIC高效傳輸體驗。
4. QUIC展望
展望未來的QUIC,機遇和挑戰並存。作為較早入局QUIC探索的開發團隊,我們除了期待更優秀的適合視訊傳輸的擁塞控制模型演算法早日出現,也期待有更多建立在QUIC之上的協議如RTMP等的出現;當然,我們也面臨著諸多挑戰,如一旦gQUIC、iQUIC或HTTP/3成為標準,那麼我們的協議棧就會面臨大範圍的改動,同時迭代更新也會增加我們的開發成本;其次,由於不存在流量控制,容易被用於流量攻擊,UDP包存在被運營商特殊對待的可能;最後是移動端的不同平臺(如Android、iOS)對QUIC的態度與支援力度,我們的願景是與全行業志同道合者一起致力於QUIC的標準化,彼此分享研究技術亮點,共同努力使使用者的音視訊流媒體觀看體驗登上一個新的高度。
精品文章推薦
技術乾貨: