构建基于浏览器的Web P2P网络直播

简介: 在2021年的互联网时代,越来越多的网络直播节目相继涌现。浏览器是用户最易接触的渠道之一,聚集了大量观看直播的用户。当用户们同时观看直播内容时,服务器承受的负载随着用户量的增加而增大,会导致播放的卡顿,延迟等用户体验的下降;而且高昂的服务器带宽成本也不容忽视。那么是否存在一套解决方案,在保证用户体验与服务质量的前提下,又可以有效的降低服务器的负载与带宽呢?那就是接下来要介绍的Web P2P技术了。

一、Web P2P的前世今生

2010年,Adobe在Flash Player 10.0推出了实时流媒体RTMFP,使用RTMFP在Flash Player之间进行P2P成为可能。在随后的几年内,该协议在网络上如雨后春笋般的被广泛部署,但是从2020年末开始,各家的浏览器都已经彻底不支持Flash了。我们又应该如何在Web里面使用P2P呢?

诞生于2011年的WebRTC技术,在Google、Microsoft、Apple、Mozilla等大厂的支持下,成为了H5的标准,并且Chrome、Edge、Safari、Firefox等主流浏览器也都支持WebRTC。所以就可以通过WebRTC来实现P2P了。

下文把基于WebRTC实现的HTML5 P2P简称为H5 P2P。

二、WebRTC简介

WebRTC的总体架构如下图所示,如果是浏览器开发者,通常需要关注并实现WebRTC C++ API,而我们的目标是基于浏览器实现P2P,所以只需要关注Web API即可。

image.png

整体的H5 P2P都是基于RTCPeerConnection和RTCDataChannel来实现的,只是实现数据层面的P2P,不包含音视频通信的内容。

三、总体架构

image.png

1. H5 P2P客户端

主要包含通信模块、传输模块、节点管理、调度模块、存储模块和统计模块:

通信模块主要负责和服务端(上图中的Index、CPS、Tracker)进行信令的通信

传输模块:包含HTTPClient和基于RTCDataChannel实现的RTCClient(上传&下载)

节点管理:不同用户间P2P主被动连接、断开、淘汰、资源信息同步

调度模块:根据buffer水位、分片信息、节点质量和规模进行CDN/P2P调度

存储模块:负责媒体数据的存储、排序、以及淘汰

统计模块:包含系统运行的埋点的实现

2. H5 P2P服务端

主要包含Index、CPS、Tracker和Stun服务:

Index:索引服务,提供其他服务地址。

CPS:资源属性服务,将直播流的URL转换为RID。

Tracker:资源追踪服务,主要存储用户和资源之间的索引关系。

MQTT:信令服务,转发用户间建立P2P连接的offer/answer/candidate SDP协议。

Stun:采用coturn部署,主要用户节点之间建立对等连接的UDP穿透。

四、阶段流程

下图简略的展示了整体方案的各个阶段、流程:

image.png

Step 1:网页打开,首先向Index服务请求其他服务的地址,保存于内存中

Step 2:客户端收到直播请求,向CPS发送请求将URL转换为资源ID(RID),相同内容相同清晰度的直播流的资源ID(RID)是相同的,表明可以互相分享数据

Step 3:客户端首先会启动HTTPClient进行数据下载,优先保证秒播。同时做以下2件事

a. 客户端向Tracker服务发送Address协议,获取其他正在观看该直播的用户地址,待后续建立连接,分享数据

b. 客户端向Tracker服务发送Publish协议,将自己的信息告知Tracker,使得别人可以即使搜索到自己,进行数据分享

Step 4:向从Tracker获取的其他用户建立连接,彼此交换信息,数据分享

五、连接建立

假设在Peer1和Peer2之间传输数据,那么在传输之前,首先需要建立连接。在WebRTC中,浏览器间通过ICE框架建立对等连接,主要包含Stun、TURN,下面分别简单介绍一下:

1. ICE

ICE(Interactive Connectivity Establishment)提供的是一种P2P连接框架,统一各种NAT穿透技术(STUN,TURN)。基于offer/answer/candidate模式,通过多次地址交换,然后进行连通性测试,穿透用户网络间各类防火墙。ICE主要包含STUN、TURN等协议。

2. STUN

STUN(Simple Traversal of UDP Through NAT)允许位于NAT设备后的客户端找到自己的公网IP/Port地址,以及查询出自己的NAT设备类型,通过这些信息使得两个同时位于NAT后的2个设备之间建立UDP通信,具体的STUN流程可以参考RFC5389,不在此赘述。

3. TURN

通俗的说,TURN(Traversal Using Relays around NAT)就是中继/转发,并不是所有的设备之间都可以依靠STUN来建立连接的,那么当两个设备之间无法依靠STUN建立连接时,就会启用TURN来进行数据中转。

由于我们的目标是节约带宽,如果采用TURN转发的话,并不能减少服务器的带宽消耗,另外一个原因是,在整个建立连接的过程中,有别于传统的视频通话只能1对1,这里的传输模式是1对多传输,所以并不要求每个连接都可靠,因此在H5 P2P项目我们仅仅通过STUN来实现连接的建立。

六、数据下载

1. 资源编码

Web P2P网络直播方案也可以同时支持任意多路直播同时进行,必须保证各路直播流之间的独立性,因此,我们提供一种统一的资源编码方式,用来标识唯一的一路直播流。这里主要借用直播流中的StreamId,通过计算MD5,生成固定长度的资源ID(RID),不仅保证了内容相同,清晰度不同,RID也不同;也保证了相同的内容,由于断流切换源地址,导致URL变化,保证资源ID(RID)相同。

2. 下载调度

在整个直播过程中,由于可播放缓存的数据是非常小的,通常不超过10秒?因此如何实时的根据当前的网络状态、网络环境,作出使用CDN,又或是使用P2P的决策呢?这里,我们的最佳实践主要如下:

a. 为了保障用户的观看体验,当缓冲区的可播数据低于某个阈值(例如5秒),就切换CDN下载

b. 当发现某一片未来的数据,周围的人都没有的时候,即使可供播放的buffer还有很多,不满足a策略的描述,这个时候,为了尽快的分发数据,也应该及时切换至CDN,出现这种情况时,往往表示这个节点以及他连接的节点都处于整个直播数据分发的顶层,为了防止出现 “一人下载多人围观” 的场景,本着更快的下载导致更早的上传理念,不仅仅要求该节点自身尽快CDN下载,同时也保证周围用户某个比例(例如15%)也尽快采用CDN下载,从而使得整体数据的分发效率提升。

3. P2P任务分配

a. 任务编号

对于每一个数据块都有一个自然数编号(sn),对于这个数据块,我们按照固定长度(默认16KB)的大小进行切分,简称chunk_index,那么(Rid, sn, chunk_index)就可以唯一确定一个数据片了。

 

b.分配请求

分配过程类似于扑克中的发牌机制,唯一的要求是对方这个节点拥有这个数据块,并且质量越好的节点,越多越分配靠近播放点的、重要的数据。下图简明扼要的展示了3个相同质量节点分配2个数据块(9个数据片)的过程。

image.png

4. 内存控制

对于Web P2P来说,所有的媒体数据都缓存在内存中,但是,也并不是会缓存完整的数据。对于直播来说,所有用户的观看点都是非常接近的,因此,内存始终缓存播放点前后的固定大小的数据。因为只有这部分数据分享利用率才是最高的。

image.png

如上图所示,有颜色的数据块都是当前在内存缓存中的数据,其中红色数据块表示当前的播放点,黄色数据块表示过去已经播放过的内容,绿色数据块表示未来还未播放的内容,可以看到当播放点从100移动至101时,97号数据块就被淘汰了,同时103号数据块作为最新的数据被下载下来并缓存到内存中。

七、工程实践

1. Goggle FlatBuffers

不管是服务器通信还是点对点的P2P传输均采用了FlatBuffers。FlatBuffers具有跨平台、内存和效率速度高,扩展灵活等优势,被我们全平台统一采用,大幅降低了通信成本。

2. 多浏览器兼容

线上支持WebRTC的浏览器不仅种类繁多,而且同一个产品的不同版本之间也可能千差万别。为了解决这一痛点,最终采用了WebRTC adapter.js来解决这一挑战。

3. 内存池

尽管Node.js自带垃圾回收机制,以及内存管理策略,但是GC和内存分配也是需要成本的,况且Web端是单线程环境,任何性能的提升都会减少时间上的损耗,进而可以处理更大吞吐的网络层传输以及业务逻辑。所以在内存分配上我们采用了内存池策略,基本实现了100%的内存重复使用。

八、技术结果

下图展示某次大型直播的带宽分时统计,显示在19:25到21:00阶段内的真实数据,随着人数的涌入和离去,Web P2P全程带来可观的带宽收益。最终评估Web P2P,在不影响用户使用体验的前提下,不仅可以有效降低服务器的负载压力,并且能够降低可观比例的带宽成本。

image.png

九、思考总结

目前,该技术已经大规模应用在各网络直播中,良好的解决了服务质量与带宽成本的平衡。但是,我们也发现在超大规模的直播下,存在了一些提升的空间,主要如下:

(1) coturn与MQTT的服务性能不高,会制约直播的服务质量。

(2) 接入边缘网络,打造多元化网络,缓解CDN负载,并且可以进一步降低CDN的带宽成本。

相关文章
|
19天前
|
存储 监控 安全
单位网络监控软件:Java 技术驱动的高效网络监管体系构建
在数字化办公时代,构建基于Java技术的单位网络监控软件至关重要。该软件能精准监管单位网络活动,保障信息安全,提升工作效率。通过网络流量监测、访问控制及连接状态监控等模块,实现高效网络监管,确保网络稳定、安全、高效运行。
46 11
|
2天前
|
运维 监控 Cloud Native
构建深度可观测、可集成的网络智能运维平台
本文介绍了构建深度可观测、可集成的网络智能运维平台(简称NIS),旨在解决云上网络运维面临的复杂挑战。内容涵盖云网络运维的三大难题、打造云原生AIOps工具集的解决思路、可观测性对业务稳定的重要性,以及产品发布的亮点,包括流量分析NPM、网络架构巡检和自动化运维OpenAPI,助力客户实现自助运维与优化。
|
2天前
|
人工智能 大数据 网络性能优化
构建超大带宽、超高性能及稳定可观测的全球互联网络
本次课程聚焦构建超大带宽、超高性能及稳定可观测的全球互联网络。首先介绍全球互联网络的功能与应用场景,涵盖云企业网、转发路由器等产品。接着探讨AI时代下全球互联网络面临的挑战,如大规模带宽需求、超低时延、极致稳定性和全面可观测性,并分享相应的解决方案,包括升级转发路由器、基于时延的流量调度和增强网络稳定性。最后宣布降价措施,降低数据与算力连接成本,助力企业全球化发展。
|
13天前
|
数据采集 机器学习/深度学习 人工智能
基于AI的网络流量分析:构建智能化运维体系
基于AI的网络流量分析:构建智能化运维体系
84 13
|
18天前
|
安全 应用服务中间件 网络安全
实战经验分享:利用免费SSL证书构建安全可靠的Web应用
本文分享了利用免费SSL证书构建安全Web应用的实战经验,涵盖选择合适的证书颁发机构、申请与获取证书、配置Web服务器、优化安全性及实际案例。帮助开发者提升应用安全性,增强用户信任。
|
26天前
|
云安全 人工智能 安全
|
30天前
|
机器学习/深度学习 人工智能 算法
深度学习入门:用Python构建你的第一个神经网络
在人工智能的海洋中,深度学习是那艘能够带你远航的船。本文将作为你的航标,引导你搭建第一个神经网络模型,让你领略深度学习的魅力。通过简单直观的语言和实例,我们将一起探索隐藏在数据背后的模式,体验从零开始创造智能系统的快感。准备好了吗?让我们启航吧!
72 3
|
2月前
|
监控 前端开发 JavaScript
使用 MERN 堆栈构建可扩展 Web 应用程序的最佳实践
使用 MERN 堆栈构建可扩展 Web 应用程序的最佳实践
30 6
|
2月前
|
数据采集 XML 存储
构建高效的Python网络爬虫:从入门到实践
本文旨在通过深入浅出的方式,引导读者从零开始构建一个高效的Python网络爬虫。我们将探索爬虫的基本原理、核心组件以及如何利用Python的强大库进行数据抓取和处理。文章不仅提供理论指导,还结合实战案例,让读者能够快速掌握爬虫技术,并应用于实际项目中。无论你是编程新手还是有一定基础的开发者,都能在这篇文章中找到有价值的内容。
|
2月前
|
存储 消息中间件 缓存
构建互联网高性能WEB系统经验总结
如何构建一个优秀的高性能、高可靠的应用系统对每一个开发者至关重要
30 2

热门文章

最新文章