草庐IT

大型直播平台应用架构浅谈

王清培 2023-11-19 原文

大型直播平台应用架构浅谈

进入直播领域有段时间了。

跟大多数同学一样,刚接触直播这个领域都非常好奇这个领域的宏观架构大概是什么样子的。

这里根据自己的这段时间学习,粗浅总结下分享给感兴趣的小伙伴扫扫盲。

目前直播平台有很多,抖/快、B站、斗/虎等。

直播这种高效的交互方式是各行业需要具备的能力,随着网络技术的发展也是必然趋势。

先抛开每家直播的内容不同之外,一个完整的直播平台至少需要包含如下几个核心功能。

观看直播、发送弹幕、打赏送礼、主播互动。

我们以一个普通的C端用户的视角,来看下这几个核心功能背后的大概应用架构。

观看直播

当我们进入直播间首先就是观看直播内容。

【拉流】

直播内容是通过 流媒体播放器 播放出来,而流媒体播放器通过 流地址 来拉取 流数据,再处理相关 解码 工作,最后呈现出画面和声音。

为了保证全国甚至海外用户都能够流畅的观看直播内容,就需要比较强大的物理网络覆盖。

流媒体数据通过上游CDN源站推(或推拉结合)到所有边缘节点。

不同地域的用户通过 全局CDN-DNS 调度后,就近访问CDN节点。

为了尽可能覆盖所有地区,不可能每家公司都去建设庞大的网络基建。

这时候就需要借助强大的公有云平台(BAT、华为、金山、字节等)。

公有云厂商砸了巨额资金建设物理链路,作为应用型企业只需要使用云产品能力即可,一切即服务。

当我们愉快的看着直播时,会好奇这些直播内容源头在哪里,这些画面是如何被采集的,数据又如何传输的。

【推流】

通常开播都有一个开播工具,开播工具是专门用来采集流媒体(音视频设备)信息及媒体流合成的,也可以用 OBS 等强大的推流工具。

当开播工具采集到媒体信息之后会进行本地压缩,然后通过 RTMP(Real Time Message Protocol) 协议将数据推送到RTMP服务器。

RTMP服务器收到流媒体数据之后,会将流信息解码并且进行 HLS(HTTP Live Streaming) 文件切片。

将RTMP服务器部署在公有云主机上,是为了借助公有云内部服务(LAAS、PAAS)的亲和性,可以最大化便捷的覆盖到CDN边缘节点。

你可能好奇,为什么推流用RTMP协议而拉流用HLS协议。

播端使用RTMP,是因为RTMP基于TCP的实时协议,可以保证推流的可靠性和实时性。

看端使用HLS是因为HLS是基于静态小文件,这就比较方便在大规模百万 PCU(Peak concurrent users ) 时,利用静态CDN容易分发的优势来覆盖。

使用HLS同时也便于在不同码率之间进行动态切换,以此来达到根据用户的网络情况选择最优的观看体验。

比如,用户处于弱网下,我们就切到低码率下观看。

用户网络良好时,我们就切到高码率下观看,同时也可以使用一些高级的观看体验和交互。

当然,HLS还有非常多的优势,在压缩、加解密等方面都非常成熟。

在2C大规模直播场景下,flv是过去时,HLS才是未来。

【P2P】

为了尽可能节省CDN带来的巨大成本,会使用 P2P(Peer to Peer) 技术来减少公有云带宽使用。

同样,为了尽可能将 STUN 服务器信令服务器 离用户近一些,这两个服务器都是部署在公有云边缘主机上。

进一步压榨成本,还可以使用 PCDN(P2PCDN) 服务。

由于公有云强大的终端网络覆盖(路由器、终端设备等)可以将CDN分发内容进一步边缘化。

利用数以万计的边缘计算能力将内容和计算一直延伸到用户末端。

其实P2P技术已经非常成熟且发展历史要比WEB互联网久远。

发送弹幕

观看直播时非常重要的一个诉求就是与主播互动,而弹幕是信息承载量最大的互动方式。

弹幕 现在已经是视频领域必不可少的媒体元素。

弹幕最早其实是在点播领域里,日本的 Niconico 算是弹幕互动的鼻祖。

A站 (Acfun)基本是国内弹幕视频网站的文化发源地 。

但是目前国内把弹幕玩出新次元的当属B站(bilibili)了。

弹幕从发送到接受,依赖 长连接 中间件。

考虑到平台可用性,长连接服务整体需要支持容灾,整个架构需要支持多机房混合部署。

在弹幕消息投递端需要做机房线路探活,根据探活后的相关数据择优选择机房。

使用公有云还有一个好处,可以享受一定额度 “对等连接” 增值服务。

整体架构越来越趋向混合云,就是为了尽可能平衡私有云的核心数据闭环,同时借助公有云强大的网络覆盖。

公有云高性能主机一般在低频下能扛个百万连接,瓶颈基本在内存和带宽。

机器成本其实还好,因为机器理论上可以无限扩展,但是带宽是有物理上限的,所以比较贵。

【舆情管控】

任何有一定体量的互联网公司,根据所处的行业和内容不同,需要对用户的参与行为进行舆情管控。

弹幕区就是需要管控的一个主要阵地,也是各安全中心所负责的核心战场之一。

弹幕的特点也恰恰是很难管控的,通常思路根据AI算法(如NLP)对弹幕内容进行前置敏感词过滤、情感分析负向过滤等。

其实,AI算法能处理的都是相对简单和容易识别的语意。

中国文字和文化博大精深,再加上复杂的词藻、词梗组合起来,就算再强大的算法都无法绝对识别。

需要人工辅助审核,人工还需要有一定的“文化”底蕴和相当广的“知识面”。

所以必然是一个非常庞大的审核队伍。

一般应用企业,做弹幕功能技术含量并不高,而且现在云厂商、开源sdk,稍微组合下架构基本就搭能起来。

反而是,安全、舆情管控才是最关键和重点投入的地方。

现在做第三方舆情发现和管控的公司也慢慢多了,社会类舆情管控公司还是比较多的,细分垂直类是比较少。

送礼打赏

在观看一段主播卖力的表演之后,就需要通过打赏来表达诚意了。

一个看似简单的送礼,其实需要涉及非常多的系统,这些系统位于不同的职责层面上。

但是不论是在直播领域还是电商、教育,基本都是类似的,只是售卖不同的商品而已。

送礼链路上,订单、账户、清结算其实是比较成熟的交易、财务模型。

这两块基本上按照模式来套,目的就是完成公司的确认收入和资金结算。

【整体链路】

我们将整个链路分两层,第一层是售卖业务层,该层由一系列售卖单元组成,比如商城、促销中心等。

在直播领域,送礼系统就是位于这一层,送礼物可以认为是一种虚拟商品的交易。

送礼场景可以非常多样化,但都是在变相的促进交易的达成。

一旦当商品售卖成功之后,根据业务性质的不同,确认收入的金额和时间点也不同。

在直播送礼中,送出去的礼物基本就是近实时确认收入,此时就需要交易订单(或叫业务订单)来承载这部分交易职责。

在售卖业务层下层是交易结算层,是收入的分账、结算、打款部分。

该部分的核心是支撑业务售卖的交易,清结算各个角色的收入。是交易结算系统最复杂的地方,也是及容易出现资损的地方。

不论我们售卖什么,要想在交易系统里完整的跑起来,首先就需要将虚拟的售卖概念进行商品化。

有了商品之后就可以通过售卖层上架去销售。

送礼本身业务比较简单,将个人账户的虚拟资产进行扣除,加到主播账户中去,就完成了业务上的基本流程。

这一步完成之后,紧接着就需要对这笔交易订单进行分账处理。需要分别计算平台、外部商家/机构等各个角色参与者分别得多少钱。

送礼成功之后至少是需要平台、主播(或工会)进行一定分成。

该部分是清结算系统中的清算部分职责,该部分通过计费、分摊分别计算好各个角色结算明细。

结算系统再通过定期捞取合同签订的结算周期(T+N/月结等)给商家结算并且打款,该部分多数是有账期的。

简言之,送礼打赏偏交易结算领域,整个系统的核心在于账务、交易、财务等业务知识。

同时在系统设计上,数据一致性、对账流程和场景是整个系统架构设计的核心。

房间互动

在直播间里,送礼不管对主播还是平台来说,都是最终目的。但是这个最终目的不可能一步达到,是需要不断的通过其他场景来转化。

直播用户的绝大部分需求是荷尔蒙需求,如何通过各种互动工具、互动形式,让用户与主播彼此多互动,才能促进送礼。

从用户视角来看互动形式主要分为三类,弹幕、手势/摇杆、送礼、视频连线

我们先来看前三种互动方式。

如抖/快双击屏幕点赞,虎牙的长按唤起快捷面板,B站的发送特殊弹幕触发“热力风暴”特效等。

同时基本每家都有的特殊礼物互动,通过赠送特殊礼物来达到房间主题变化、主播装扮变化等。

所有的互动形式我们都需要统一的进行抽象管理,可以用一句话概括: “在指定的房间指定的时间段,启用一个或多个互动活动/玩法”

至于某个具体的互动玩法,该玩法需要哪些素材,需要哪些触发媒介,除了通道部分可以走订阅方式,其他都需要定制开发。

比如,弹幕互动中的蓄力类的,除了通用的弹幕通道之后,哪些词,在多少时间窗口内命中多少次,然后触发什么业务逻辑。

或连击送礼蓄力类,除了送礼通道是通用部分之外,哪些礼物,在多少时间窗口内送出多少个,金额满足多少都属于业务逻辑需要捕获和处理的地方。

整个互动是需要打通看端和播端。

看端特效和播端特效是有明显区别的,看端多数是在直播间里可以交互的特效元素,而播端特效最终是在流里体现的。

比如,一个送礼互动特效,用户“连续”赠送礼物到达一定的阈值就触发播端的互动逻辑,最终将消息输入到流里,同时看需求是否添加 SEI(Supplemental Enhancement Information) 信息。

【视频连线】

与前三种互动方式不一样的是,视频连线是基于音视频技术的通用能力,强依赖多媒体技术栈,涉及到编解码、合流等。

不仅可以用在用户与主播连线,主播与主播也可以基于视频连线能力扩展很多互动形式,如视频PK(Battle)等。

我们看下主播与主播的视频连线整体流程。

整个流程基于频道(channel)做为外部供应商和内部服务的一个逻辑上下文,用来串联客户端、服务端、外部sdk。

该架构通过外部sdk合流,会增加一定的带宽成本,属于不那么经济的方案,最大的好处是实现简单并且可以保证观看端音画同步。

房间主题

如果我们将直播间比喻成现实中的房间,我们希望是千人千面的,并且具有一定的定制性。

同时,我们希望房间可以根据日历自动感知到节日的 娱乐性 、 严肃性 。

如果将直播间比喻成线上的社区单元,那此地也不是法外之地,需要受到不同程度的舆情、社敏性、法律安全监管。

直播间按照业务形态划分,有非常多的维度去分,比如商业化房间(带货/电商/分销)、游戏房间、K歌房、放映厅等。

最终,不同的房间需要开放、管制一些能力,互动娱乐,送礼,主播行为等。

日历和主题管理是整个房间生成的基础基因。

需要对房间整个架构进行工程化设计,要面向接口、面向开放标准。

只有这样才能具备定制性和扩展性。

整个房间大概有几个核心区域, ___送礼区、播放器区、弹幕区、互动区。

这几个区域的实现需要分成两层,第一层实现最核心的内核基础功能。

这部分功能可以直接排除主题相关性。

第二层是其他带有装饰的功能,这部分实现需要具备主题感知能力。

在此基础之上,我们假设实现一个弹幕区的特殊弹幕效果。

该实现插件通过工程化接口和标准,拿到日历&主题便可以感知到节日的属性。在实现上可以分离出基础功能和效果功能。

这样设计还便于将效果类功能做全年的特殊节日的自动化测试和业务巡检。

房间推荐算法需要加入日历推荐因子,这部分是比较好理解的。比较有意思的是房间构造中心才是房间成品的出口。

活动保障

最后分享下技术保障方面的内容。

这部分就精简总结下,不叙述过程。

简言之,保障主要关注两个重点。

第一个重点是我们大多数比较熟悉的应用系统常规的抗高并发,这里包括一系列的中间件、DB、缓存、微服务套件等。

第二个重点是跟PCU相关的线性资源CDN带宽、P2P带宽、长连带宽、打点、实时报表计算等。

按照看、播两端分别来看。

播端,需要重点保障推流的可用性,所以基本上在推流侧至少有两路流互相backup。

看端,QPS、TPS相关接口基本是斜率或突增流量相关。

(注:某接口峰值可以扛住10wQPS,到达这个峰值是每秒钟加1w缓慢增加,还是1s到达10w是不一样的。)

斜率本质考验的是后端相关资源的扩容速度。

在大并发场景下,有时候我们需要提前扩容就是为了防止突增流量。

这也是按照斜率来评估扩容资源的难点。

另外一方面是跟PCU线性相关的。

PCU直接带来的是相关公有云带宽、连接池等比例增加,这部分需要做好资源预购。

当在线的人数非常高时,数据上报、实时数据处理也都是线性增加的。

这部分存储资源是需要提前预备好,计算资源可以适当弹性调度。

所有上述场景在合理的容量范围内系统都可以承载,但是一旦有非预期的流量进来我们也要有自我保护的机制和拉闸能力。

这部分相关的,限流、降级能力也是必不可少的。

有关大型直播平台应用架构浅谈的更多相关文章

  1. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  2. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  3. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  4. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  5. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  6. ruby-on-rails - 如何在 Gem 中获取 Rails 应用程序的根目录 - 2

    是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在

  7. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  8. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  9. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  10. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

随机推荐