怎麼在b站做一名up主(B站Up主上傳質量調優實踐)
2023-04-20 09:24:24 1
Up主上傳的大量優質視頻內容使得bilibili(B站)深受年輕用戶的喜愛。bilibili視頻雲高級研發經理 唐君行在LiveVideoStack線上交流分享中詳細介紹了B站為提供更流暢、穩定用戶體驗,努力優化上傳系統架構,建立質量體系以及質量調優中的實踐經驗。
文 / Json(唐君行)
整理 / LiveVideoStack
直播回放:
https://www.baijiayun.com/web/playback/index?classid=19012252228433&token=oxx9-k_ZrxvhKKZLIMQ5hscti3kMCPTn5jjVy0_0ZBG_6qrsbCBq-khAVqheOz1TCqdH1zJ1Si0
大家好,我是來自bilibili(B站)的Json,目前主要負責bilibili的視頻上傳、存儲、點播CDN建設與架構演進。在進入B站之前我主要負責系統架構設計與數據驅動研發,同樣這也是我非常擅長的領域。
我將從以上幾個方面為大家分享B站上傳調優實踐的具體內容:兩三年前,B站伺服器有限的承載能力使得用戶上傳視頻失敗的狀況時有發生,這也是我剛加入B站時希望通過調整系統架構努力優化的方面;同時這樣一個基於數據優化的項目,需要建立正確的優化指標與質量優化方案,藉助數據的力量驅動整個平臺的開發,使得用戶能夠在B站收穫流暢穩定的使用體驗。
1. 系統架構
上圖展示的是B站的用戶創作中心,用戶上傳到B站的視頻文件體積較大,質量較高。初期我們僅開發了通過PC(網頁端)上傳文件的功能。視頻體積較大是我們的優化工作帶中的主要挑戰,因為只有所有分片都上傳成功,一個視頻文件才算被上傳成功。
B站為了確保內容的高質量,僅有答對一定數量題目的Up主才能獲取上傳視頻的資格,這就使得上傳至B站的視頻內容多為平均體積在400MB左右的優質長視頻;雖然採取了這種設置一定門檻的上傳機制,但我們的日上傳量依舊保持在15萬左右並且維持著年100%的增長,這也就是為什麼在未來我們希望在鞏固現有網頁版上傳服務的同時繼續開發Android、iOS、PC客戶端的上傳功能,方便用戶隨時隨地上傳高質量視頻內容。
作為上傳系統的關鍵組件,存儲部分的架構並不複雜。我們使用一臺節點伺服器處理數據提供服務,當用戶將視頻文件成功上傳至此伺服器時,視頻文件在伺服器後端會經過一系列系統處理,並在主機之間多次交換數據,其傳輸協議與溝通方式更像一個運維系統,比較原始,我們將其重構為一個帶有網關的系統,改進原先每開始一種新業務就需新分配一批伺服器的機制,使用網關的匯集功能可大大降低在配置域名與接入新業務等運維工作的壓力與成本,並將節省下來的時間資源運用於優化工作。
除此之外,我們將統一存儲升級為可以分Bucket配置不同參數且與業務無關的通用對象存儲,其承接了B站的UGC、PGC、音頻、短視頻的上傳、處理與回源等工作;同時,使用此上傳、存儲體系統一的方案可有效減少文件在系統間轉移產生的IO。
隨著B站的不斷發展,從一開始投入大量資源至業務發展到現在逐漸專注於內容與資源的分享與呈現,B站不斷嘗試將主要精力從與業務相關的內容剝離出並投入優化工作,基於此網關統一所有業務的通訊協議從而進一步簡化存儲架構。
我們基於OpenResty搭建了B站的上傳系統。初期B站的上傳系統基於PHP搭建,雖然PHP並沒有明顯缺陷,但由於其還需搭建Nginx才能正常工作,因此相對於OpenResty這樣可直接在Nginx中讀取與合併上傳文件分片的架構,PHP並不是我們的首選項。使用OpenResty的同時,對外發起Gap請求的次數也更多,同樣也支持用戶從網站獲取視頻數據的高性能模式。純粹從程式語言層面來講 ,以上是OpenResty在網關層面的作用之一。就我目前的體驗來看,OpenResty並不輸給其他語言:我們的視頻雲中包括大量基於OpenResty架構的技術棧,而CDN、存儲系統與直播系統也基於OpenResty實現,推薦大家使用OpenResty。
一般大公司會使用OpenResty重寫相應模塊以應對高並發場景,實際來說我們可在一些高I/O場景中使用OpenResty。雖然Node.js與Go也可實現異步I/O但其需要開發者編寫大量的回調,而OpenResty能夠藉助同步代碼實現異步I/O;相對於需要大量時間精力應對高並發場景的Python與PHP,OpenResty可極大提高開發效率。除此之外,Nginx本身也扮演著網關與業務服務的角色,可明顯簡化架構;OpenResty也可直接訪問Nginx的ClientBody且不存在語言框架的損耗,如果是其他語言則需在CGI層通過上行Buffer將ClientBody傳至所用語言中,並且需要一定轉化如Python需要WSGI轉化;最後,Lua較高的開發效率也能幫助開發者儘可能實現最佳開發效果。
上圖展示了存儲系統的整體架構,其主要分為以下三個模塊:網關、Meta資料庫與存儲。用戶的訪問請求首先經由網關處理,網關繼而讀取Meta資料庫中一部分符合請求存儲位置的數據,隨後存儲會將網絡流依次通過圖中的路徑5與路徑6傳輸至客戶端。這樣一個簡單的存儲架構自然而然會受到許多需要重構小部分存儲減小內容存儲風險的公司的青睞。
我們選擇S3作為上傳協議。在早期上傳協議的選型過程中我們研究了國內許多網際網路公司的選型策略,其實國內的大部分網際網路公司所採取的上傳協議都類似於亞馬遜的S3協議,因此我們在構建B站的上傳存儲系統時直接使用了亞馬遜的這一協議,其優勢不僅在於亞馬遜的上傳協議本身就很完善,更在於我們可直接復用亞馬遜S3生態中的大量組件。無論是在分片上傳、分片大小、並行數量還是在其他我們能想到的可用於關鍵技術上的優化,通過長期的實踐與探索亞馬遜已將其一一實現,不得不說這明顯降低了我們的開發難度與工作壓力。
S3上傳協議的整體流程如上圖展示:首先,初始化過程會在服務端為用戶分配一定空間,隨後來自客戶端的數據會通過並行上傳發送至服務端;在這裡我們考慮優化整個上傳過程,為提升上傳速度與上傳體驗我們使用並行上傳的方式分片傳輸數據;在這些數據被存儲於服務端時,客戶端會生成與並行傳輸相關的會話,此會話會被服務端讀取從而將所有分片正確合併。
S3上傳協議共需三個請求:用於分配上傳空間的Uploads、用於並行上傳的Put與用於合併完整文件的Post-complete。其中Put用於並行上傳,並行上傳時分片大小可自己定義,分片的順序則通過PartNumber標示;在合併文件時服務端根據PartNumber所標示的不同順序正確組合所有分片合併生成完整文件並在最後進行校驗從而確保合併完整文件的正確無誤。
上圖展示的便是整個上傳系統與後續工作的簡化架構。首先,客戶端會請求上傳調度,其實如果按照中心存儲架構重構來說上傳調度並非必要流程,這裡設計上傳調度的目的是便於後續優化工作的進行:上傳調度可為客戶端分配用於將數據上傳至CDN的不同地址與不同上傳模式。緊接著在客戶端請求完成調度並將數據上傳至存儲之後,存儲會產生一條可驅動視頻處理流程的消息,從而啟動轉碼、截圖、審核、分發等一系列圍繞存儲進行的流程。與此同時,存儲會接受所有上傳分片並產生相應日誌,這些日誌會被傳輸至日誌中心並呈現給負責分析的運維人員或作為可優化上傳調度過程提升用戶體驗的信息使用。
2. 建立指標
擁有上傳架構之後,我們需要建立完善的指標體系。音視頻行業有與播放相關的首幀、卡頓率等用於表徵用戶播放體驗的指標參數。我們可憑藉這些指標反映出的動態變化規律對用戶的多方面體驗做出優化。對於上傳過程而言,大家比較容易想到的與用戶上傳體驗相關的指標,首先就是分片上傳的瞬時速度——瞬時速度決定數據上傳的耗時,耗時越短用戶體驗越優秀;但瞬時速度的計算非常複雜,且無法明確幫助我們實現期待的優化目標。慢速比也是十分關鍵的指標之一,但慢速比不但不滿足線性相關關係,同樣難以幫助我們實現優化目標。瞬時速度與慢速比並不能很好體現用戶上傳體驗的優劣,我們希望建立一些能夠幫助我們實現優化目標的指標,且計算過程相對簡單,允許我們通過數據儘可能詳細量化優化所帶來的用戶體驗的變動。經過不斷探索我們將全局均速與成功率作為評價用戶上傳體驗的兩項關鍵指標——全局均速的定義是使用一個用戶所上傳文件的體積除以上傳時間得到的一個以兆每秒為單位的物理量,成功率則是用戶完成上傳的次數除以用戶發起上傳的次數,而後將結果乘以100%。通過長時間的實踐,我們可以說此兩項指標能夠客觀準確地反映出用戶上傳體驗的優劣程度。
數據閉環值得我們在優化過程中重點關注。將用戶反饋與上述指標體系中的關鍵數據相結合,我們便能得到有助於優化整個上傳系統的關鍵參考信息,從而得到調試所需的最佳技巧方案。比如我們需要從多家CDN中選出合適的作為接入服務商,那麼就可根據比較各家方案的全局均速與成功率判斷第三方CDN的上傳質量。這裡需要強調的是,有些可以明顯提升傳輸速度的優化方案會降低傳輸成功率,這就使得我們在對比時一定要綜合考慮這兩項指標;而像分片體積、並發數、重試次數等對上傳成功率造成影響的參數,就需要我們通過建立abtest數據閉環納入考量。
除了上述內容,比較不同平臺的上傳質量同樣至關重要。初期B站僅有Web端上傳,使用手機與PC訪問Web端上傳同樣的文件,PC端的成功率明顯高於移動端。我們需要在比較不同平臺上傳質量時儘可能規避由平臺限制造成的影響因素,從而得到傳輸鏈路本身對用戶上傳體驗的影響。
3. 質量優化3.1 鏈路層面優化
鏈路層面的優化至關重要,其中不可或缺的條件便是CDN。初期我們的方案是接入多家上傳CDN,但多家CDN良莠不齊,對用戶體驗的影響也存在差異;隨後我們通過調研發現許多大公司會選擇通過建立BGP直連或CDN節點加速的方式傳輸數據,而這兩種方案對邊遠地區或小規模運營商的支持並不完善;ab對比上傳指標同樣是鏈路層面優化的一項重要參考,但最後我們明確了將選用節點數較多的CDN運營商作為數據上傳技術支持的思路,CDN公司所提供的節點數量直接決定了數據上傳的質量。
3.2 客戶端選線VS服務端選線
身處不同地區的用戶如何選擇最佳傳輸路線?客戶端選線與服務端選線哪一個是最佳方案?這些都是值得我們研究探索的命題。服務端優化的思路之一是我們可通過在服務端建立資料庫並記錄某一地區用戶的上傳質量為這一地區分配優選CDN,但在實際應用中,相對於隨機分配路線的策略,此方案並未收穫令人滿意的性能與質量提升;通過進一步探索我們發現,客戶端在上傳前對線路進行探測能夠有助於實現較高傳輸質量。具體思路是在數據上傳前先藉助小範圍客戶端進行一次簡單的包探測並與預設方案進行比較從而得到最佳優化方案。
使用電信網絡的用戶易被上下行寬帶不對等的問題所困擾,鑑於此我們與電信運營商進行交涉,通過IP庫檢測電信用戶並為其打開電信上傳限制,通過上述優化可使電信用戶的上傳速率提升10倍左右。
3.3 JSSDK優化
對於JSSDK的優化主要是通過將多文件並發的策略改為文件內分片並發實現,前者相當於多個文件同時佔用一個上行總帶寬,造成的結果是三個文件的上傳均十分緩慢;而後者則可明顯提升文件傳輸效率。
支持將數據上傳到第三方存儲可以說是我們為用戶充分考慮而設計的一項優化,來源於客戶端的數據會先被上傳至第三方存儲並通知原站將其從第三方存儲拉取回原站存儲,這樣的好處在於可以讓一些身處距離較遠如海外等不方便直連原站存儲的用戶享受到近距離節點用戶的上傳體驗,例如將原先海外客戶端與國內直連改成國外客戶端將視頻先上傳至如亞馬遜等第三方海外節點,而後國內原站存儲再從第三方海外節點拉取視頻數據,用較低成本實現良好傳輸效果。
3.4 跨會話上傳控制
通過大數據我們發現周末上傳成功率下降明顯,從用戶行為的角度分析其原因在於周末Up主人均上傳稿件數量增多,很多用戶會選擇打開兩個甚至多個播放器進行並發上傳,這對帶寬資源的佔據是顯而易見的。為應對此情況我們使用js的LocalStorage實現鎖,實現了將周末視頻文件的上傳成功率相較於工作日時期提升1%左右的優化。
2018年我們上線了移動端上傳服務,其中的一項關鍵優化在於服務端下發參數以便於數據驅動優化。移動端與Web端最大的區別在於移動端的發版代價更大,通過上報網絡環境與主機型號等得到服務端的下發參數,利用數據驅動優化,從而將發版代價巨大的移動端場景轉換為與Web瀏覽器類似的一種易於服務端與數據驅動優化的場景,從而通過調整不同參數實現移動端的最佳上傳服務。相對於基於無線網或寬帶網絡等環境與質量較高的Web瀏覽器端,基於行動網路的手機移動端可能無法提供傳輸所需的高質量網絡環境,面對這種情況我們會根據網絡環境的不同為移動端匹配最合適的節點,優選並發數、分片體積、重試次數與間隔等,確保移動端用戶上傳體驗的一致性。
4. 總結與成果
通過重構系統、建立指標體系、優化指標與明確達成目標等一系列舉措,我們得以將上傳成功率從最初的的85%提升至94%,同時實現平均速度提升4倍,實現用戶相關投訴0記錄的優化成果,與此同時我們是業界少有的能夠較好支持網頁端並行上傳的視頻平臺。
關於未來我們探索的方向,我們希望藉助QUIC上傳優化移動端的上傳體驗,並為實現動態切換上傳線路而不斷努力以達成高可用與更佳的體驗優化。
,