如何設計一個 70w 線上人數的彈幕系統 ?

来源:https://www.cnblogs.com/javastack/archive/2023/04/05/17289524.html
-Advertisement-
Play Games

原文:cyningsun.com/03-31-2019/live-streaming-danmaku.html 背景 為了更好的支持東南亞直播業務,產品設計為直播業務增加了彈幕。第一期彈幕使用騰訊雲支持,效果並不理想,經常出現卡頓、彈幕偏少等問題。最終促使我們開發自己的彈幕系統。性能要求是需要支持, ...


原文:cyningsun.com/03-31-2019/live-streaming-danmaku.html

背景

為了更好的支持東南亞直播業務,產品設計為直播業務增加了彈幕。第一期彈幕使用騰訊雲支持,效果並不理想,經常出現卡頓、彈幕偏少等問題。最終促使我們開發自己的彈幕系統。性能要求是需要支持,單房間百萬用戶同時線上。

問題分析

按照背景來分析,系統將主要面臨以下問題:

  1. 帶寬壓力

    假如說每3秒促達用戶一次,那麼每次內容至少需要有15條才能做到視覺無卡頓。15條彈幕+http包頭的大小將超過3k,那麼每秒的數據大小約為8Gbps,而運維同學通知我們所有服務的可用帶寬僅為10Gbps。

  2. 弱網導致的彈幕卡頓、丟失

    該問題已線上上環境

  3. 性能與可靠性

    百萬用戶同時線上,按照上文的推算,具體QPS將超過30w QPS。如何保證在雙十一等重要活動中不出問題,至關重要。性能也是另外一個需要著重考慮的點。

帶寬優化

為了降低帶寬壓力,我們主要採用了以下方案:

  1. 啟用Http壓縮

    通過查閱資料,http gzip壓縮比率可以達到40%以上(gzip比deflate要高出4%~5%)。

  2. Response結構簡化

  3. 內容排列順序優化

    根據gzip的壓縮的壓縮原理可以知道,重覆度越高,壓縮比越高,因此可以將字元串和數字內容放在一起擺放

  4. 頻率控制

  • 帶寬控制:通過添加請求間隔參數(下次請求時間),保證客戶端的請求頻率服務端可控。以應對突發的流量增長問題,提供有損的服務。
  • 稀疏控制:在彈幕稀疏和空洞的時間段,通過控制下次請求時間,避免客戶端的無效請求。

彈幕卡頓、丟失分析

在開發彈幕系統的的時候,最常見的問題是該怎麼選擇促達機制,推送 vs 拉取 ?

Long Polling via AJAX

客戶端打開一個到伺服器端的 AJAX 請求,然後等待響應,伺服器端需要一些特定的功能來允許請求被掛起,只要一有事件發生,伺服器端就會在掛起的請求中送迴響應。如果打開Http的Keepalived開關,還可以節約握手的時間。

優點: 減少輪詢次數,低延遲,瀏覽器相容性較好。缺點: 伺服器需要保持大量連接。

WebSockets

長輪詢雖然省去了大量無效請求,減少了伺服器壓力和一定的網路帶寬的占用,但是還是需要保持大量的連接。那麼人們就在考慮了,有沒有這樣一個完美的方案,即能雙向通信,又可以節約請求的 header 網路開銷,並且有更強的擴展性,最好還可以支持二進位幀,壓縮等特性呢?於是人們就發明瞭這樣一個目前看似“完美”的解決方案 —— WebSocket。它的最大特點就是,伺服器可以主動向客戶端推送信息,客戶端也可以主動向伺服器發送信息,是真正的雙向平等對話。

優點:較少的控制開銷,在連接創建後,伺服器和客戶端之間交換數據時,用於協議控制的數據包頭部相對較小。在不包含擴展的情況下,對於伺服器到客戶端的內容,此頭部大小隻有2至10位元組(和數據包長度有關);對於客戶端到伺服器的內容,此頭部還需要加上額外的4位元組的掩碼。相對於 HTTP 請求每次都要攜帶完整的頭部,此項開銷顯著減少了。更強的實時性,由於協議是全雙工的,所以伺服器可以隨時主動給客戶端下發數據。相對於HTTP請求需要等待客戶端發起請求服務端才能響應,延遲明顯更少;即使是和Comet等類似的長輪詢比較,其也能在短時間內更多次地傳遞數據。長連接,保持連接狀態。

Long Polling vs Websockets

無論是以上哪種方式,都使用到TCP長連接,那麼TCP的長連接是如何發現連接已經斷開了呢?

TCP Keepalived會進行連接狀態探測,探測間隔主要由三個配置控制。

keepalive_probes:探測次數(預設:7次)

keepalive_time 探測的超時(預設:2小時)

keepalive_intvl 探測間隔(預設:75s)

但是由於在東南亞的弱網情況下,TCP長連接會經常性的斷開:

Long Polling 能發現連接異常的最短間隔為:min(keepalive_intvl, polling_interval)

Websockets能發現連接異常的最短間隔為:Websockets: min(keepalive_intvl, client_sending_interval)

如果下次發送數據包的時候可能連接已經斷開了,所以使用TCP長連接對於兩者均意義不大。並且弱網情況下Websockets其實已經不能作為一個候選項了

  • 即使Websockets服務端已經發現連接斷開,仍然沒有辦法推送數據,只能被動等待客戶端重新建立好連接才能推送,在此之前數據將可能會被採取丟棄的措施處理掉。
  • 在每次斷開後均需要再次發送應用層的協議進行連接建立。

根據瞭解騰訊雲的彈幕系統,在300人以下使用的是推送模式,300人以上則是採用的輪訓模式。但是考慮到資源消耗情況,他們可能使用的是Websocket來實現的彈幕系統,所以才會出現彈幕卡頓、丟失的情況。綜上所述,Long Polling和Websockets都不適用我們面臨的環境,所以我們最終採取了短輪訓 的方案來實現彈幕促達

可靠與性能

為了保證服務的穩定性我們對服務進行了拆分,將複雜的邏輯收攏到發送彈幕的一端。同時,將邏輯較為複雜、調用較少的發送彈幕業務與邏輯簡單、調用量高的彈幕拉取服務拆分開來。服務拆分主要考慮因素是為了不讓服務間相互影響,對於這種系統服務,不同服務的QPS往往是不對等的,例如像拉取彈幕的服務的請求頻率和負載通常會比發送彈幕服務高1到2個數量級,在這種情況下不能讓拉彈幕服務把發彈幕服務搞垮,反之亦然,最⼤度地保證系統的可用性,同時也更更加方便對各個服務做Scale-Up和Scale-Out。服務拆分也劃清了業務邊界,方便協同開發。

在拉取彈幕服務的一端 ,引入了本地緩存。數據更新的策略是服務會定期發起RPC調⽤從彈幕服務拉取數據,拉取到的彈幕緩存到記憶體中,這樣後續的請求過來時便能直接⾛走本地記憶體的讀取,⼤大幅降低了調用時延。這樣做還有另外一個好處就是縮短調⽤鏈路,把數據放到離⽤戶最近的地⽅,同時還能降低外部依賴的服務故障對業務的影響,

為了數據拉取方便,我們將數據按照時間進行分片,將時間作為數據切割的單位,按照時間存儲、拉取、緩存數據(RingBuffer),簡化了數據處理流程。與傳統的Ring Buffer不一樣的是,我們只保留了尾指針,它隨著時間向前移動,每⼀秒向前移動一格,把時間戳和對應彈幕列表並寫到一個區塊當中,因此最多保留60秒的數據。同時,如果此時來了一個讀請求,那麼緩衝環會根據客戶端傳入的時間戳計算出指針的索引位置,並從尾指針的副本區域往回遍歷直至跟索引重疊,收集到一定數量的彈幕列表返回,這種機制保證了緩衝區的區塊是整體有序的,因此在讀取的時候只需要簡單地遍歷一遍即可,加上使用的是數組作為存儲結構,帶來的讀效率是相當高的。

再來考慮可能出現數據競爭的情況。先來說寫操作,由於在這個場景下,寫操作是單線程的,因此⼤可不必關心併發寫帶來的數據一致性問題。再來說讀操作,由圖可知寫的方向是從尾指針以順時針⽅向移動,⽽讀⽅向是從尾指針以逆時針方向移動,⽽決定讀和寫的位置是否出現重疊取決於index的位置,由於我們保證了讀操作最多只能讀到30秒內的數據,因此緩衝環完全可以做到無鎖讀寫

在發送彈幕的一端 ,因為用戶一定時間能看得過來彈幕總量是有限的,所以可以對彈幕進行限流,有選擇的丟棄多餘的彈幕。同時,採用柔性的處理方式,拉取用戶頭像、敏感詞過濾等分支在調用失敗的情況下,仍然能保證服務的核心流程不受影響,即彈幕能夠正常發送和接收,提供有損的服務。

總結

最終該服務在雙十二活動中,在Redis出現短暫故障的背景下,高效且穩定的支撐了70w用戶線上,成功完成了既定的目標。

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發佈,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • FreeRTOS的heap_4記憶體管理演算法具有記憶體碎片合併的功能,可以有效防止記憶體碎片產生,使用First fit演算法,在實現上與C標準庫的malloc類似,但是效率更高且能進行碎片合併回收。以下是個人對源碼的解析,有空再補充詳細。 一、初始化 static void prvHeapInit( vo ...
  • JVM調優,其實就是調整SWT和FGC的過程 JVM記憶體模型 通過一張基礎的圖瞭解最簡單的JVM模型: 其實在jvm模型中,主要包含了我們常見的堆棧方法區等待--每個版本不同可能解釋有所不同,這裡預設以8版本為例: 首先給出官方文檔的解釋: https://docs.oracle.com/javas ...
  • 項目實例:- 命令行程式 一、實例:接收命令行參數 本章內容 12.1 接收命令行參數 12.2 讀取文件 12.3 重構:改進模塊和錯誤處理 12.4 使用 TDD(測試驅動開發)開發庫功能 12.5 使用環境變數 12.6 將錯誤消息寫入標準錯誤而不是標準輸出 創建項目 ~/rust ➜ car ...
  • Week3 Exceptions Fuel Gauge 題目描述: 輸入分數字元串,判斷並輸出相應的百分數;特例不足1%輸出E,超出99%輸出F 思路: 1,從字元串中取出x,y; 2,按題中要求計算輸出; 題解: while True: try: ## 取出x,y x, z, y= input(" ...
  • 低代碼平臺技術目前在國內外都發展迅猛。早在低代碼的概念完善之前, Salesforce 公司就在1999年提出了"軟體終結"的口號,並面向開發者研發了http://force.com應用開發平臺,允許開發者基於此快速開發 CRM 軟體系統,從而開啟了低代碼應用開發的航程。 OutSystems 和 ...
  • php-ast php-cs-fixer PHP-CS-Fixer 是一個開源工具,它可以強制執行和檢測違反 PHP 編碼風格的行為。 使用預定義的規則,它可以使您擁有嚴格的編碼風格,該風格由工具強制執行,因此您可以將時間花在更重要的事情上。 安裝過程 在github上其實給出了很多種安裝方式,我直 ...
  • 僅作為筆記 GUI繼承體系圖 Frame創建 public class Test{ public static void main(String[] args){ //新建Frame Frame frame = new Frame("This is frame title"); //設置可見性 fr ...
  • chromedriver簡單使用 自動瀏覽 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...