美文网首页
如何为直播视频构建大规模消息系统

如何为直播视频构建大规模消息系统

作者: Go语言由浅入深 | 来源:发表于2022-05-27 07:14 被阅读0次

问题描述:
视频是分享事件和交流的非常有效的媒介。它可以是zoom视频会议,也可以是Facebook的直播视频,甚至是一些体育赛事的直播。但是,为了让这些视频流更具吸引力和互动性,就需要在这些实时信息流上发送消息,比如直播评论,在视频通话聊天中分享一些消息,评论某人在观看体育赛事时的感受等等。

这种通过视频流共享评论的机制带来了多重挑战,其中之一是如何构建一个能够处理大规模可变负载的系统。这种情况的一个例子是体育赛事的现场直播,如印度/新西兰的WTC决赛。比赛的观众人数约为2500万,是迄今为止所有直播赛事中最高的。一般情况下,负载不会很高,但在发生此类事件时可能会有高负载,因此构建的系统必须能处理此类突发情况。

在本文中,我们将讨论如何为这样的大规模实时流系统构建评论或类似功能。我们不讨论如何优化大规模视频直播流。

系统常见需求:

  • 所有用户都能够随时发表评论。
  • 评论能实时地传递给所有的观看视频用户。
  • 系统应该与实时视频流解耦,因为这不是关键内容。
  • 发送的消息是实时的,因此如果用户在时间T1之后加入,它将只看到该时间戳之后的评论。
  • 消息可以通过不同的设备传递。
  • 消息需要传递给所有的观看者,而不考虑他们的地区。
  • 系统应该具有高可用性和可伸缩性。

下面开始:

宏观上,系统类似如下所示:



如图所示,Alice和Bob都在同一个直播中进行互动。这里Alice想要发表评论,所以他将评论发送给消息服务(Messaging service),消息服务将评论传递给当前正在观看直播流的所有用户(在本例中是Bob)。

假设

1、这里,我们将更多地关注Messaging Service,因此我们假设安全问题,如认证、ssl、限流等已经解决。
2、用户管理功能也已就绪。
3、此外,我们并不关注用户查看消息的UI。
4、一个用户每次只能加入一个直播。
现在我们深入设计并理解系统的不同组件:


组建描述

Message Service
1、这是API服务器,它将接收用户对特定视频流的评论/类似请求。
2、消息服务接收到用户请求后,将执行一些基本的验证,然后将请求推送到最近的分发器(Dispatchers),该分发器和消息服务运行的同一区域。

分发器(Dispatcher)

分发器从队列里面读取消息后做出以下动作:
1、从请求中读取视频流ID, 找出所有与该流有活动连接的管理服务(supervisors)。
2、将消息推送给所有的连接管理服务(supervisors)。
3、因为流的连接管理服务也可以在不同的区域,所以dispatcher也会将它收到的消息分发到所有区域的dispatcher队列中。
4、这里,随着SQS(简单队列服务)负载的增加,dispatchers的数量也可以根据SQS中未读消息的数量进行伸缩。从而实现独立缩放。


用户连接管理服务(Supervisor)

Supervisor服务从SQS读取消息将作如下动作处理:
1、找到所有观看直播的用户。
2、发送消息给观看直播的用户。
3、如果并发连接数量增加,则可以扩展管理服务(supervisor)的数量。
4、当用户开始观看直播时,将与supervisor建立websocket连接。websocket与服务器绑定,因此一台服务器可以处理的并发连接数量是有限的。为了扩展supervisor会使用负载均衡器。


业务流程

1、Alice和Bob同时在观看视频流1。
2、当用户开始观看视频流时,会与supervisor建立长连接。
3、Supervisor将数据(视频流id和用户id关联)存储在它的缓存中。
4、用户会向supervisor发送心跳说明连接的活跃状态。如果在指定的时间内没有接收到心跳,那么连接将被认为是失效的,并将从supervisor缓存中删除。
5、用户在与supervisor建立连接后,它将调用dispatcher服务来注册某用户已经开始观看视频流。
6、Dispatcher将在其缓存中存储该数据(视频流id和supervisor-id)。
7、现在连接到视频流1的Alice将通过Message service服务的API发送对该流的评论。
8、Message Service服务将评论消息发送到最近的dispatcher服务。
9、Dispatcher将检查它的缓存,找出所有包含用户和该视频流连接的supervisor服务,并将消息推送到相关的supervisor服务。
10、supervisor在接收到消息后将检查它的缓存以找到所有正在观看视频1的用户,并将消息通过websocket连接推送给所有观看的用户。

日志和监控

1、所有应用程序和事件日志都将被推送到ELK(日志搜集服务)。
2、服务的性能参数会推送到类似hyper-trace, data-dog的应用性能管理服务(APM)。开发团队能够设置仪表盘和警报,从而使他们能够了解系统的健康状况。

弹性扩展

在上述系统中,所有组件都是松耦合的,可以很容易地独立扩展。
1、如果API调用的数量增加,则可以扩展message service服务实例来处理负载。
2、如果SQS中的消息数量增加,那么可以扩展dispatcher节点的数量来处理更多的消息,从而保持服务质量。
3、如果并发用户连接数增加,supervisor节点可以扩展以处理更多的连接。
注意:尽管自动伸缩对处理流量很有用,但它也有各种限制,如容量不足的误报、启动新服务器需要时间,通常比流量增加慢、自动伸缩组限制(如每个自动伸缩组只有一个实例)等。因此,为了处理繁重的负载,我们不应该只依赖于自动扩展。

长连接的高效管理

由于活跃连接的数量可能非常大,以飞快的速度增加。因此,必须有一些适当的策略来有效地维护这些连接,处理这么多连接的系统不可能无限扩展。

存在大量连接的原因:

1、实际流量非常高。
2、旧的连接未被正确地终止,因为所有的客户端并不总是优雅地关闭。
3、存在大量闲置连接,这些连接没有被使用很长时间。

管理大量并发长连接的策略

1、使用异步I/O(event poll)来管理连接,这样可以增加由单个服务器管理的连接数量。这将优化服务器的资源利用,但增加了代码的复杂性。
2、分配TTL到每个连接。为每个连接分配随机的TTL,以便在指定的时间后终止连接,如果需要,客户端可以重新建立连接。注意:当分配TTL时,所选择的时间应该是随机的,这样我们就不会陷入雷群问题。
3、通常服务器不会从它的一端关闭连接,所以服务器可以向客户端发送终止信号,这样客户端可以侦听信号并关闭当前连接,需要时再建立一个新的连接。

服务特点

1、使用Kibana作为日志和监控。
2、当不同组件之间使用流时,负载均衡可以在不同的点上使用。
3、由于服务是使用EKS部署在云上的,因此可以实现水平扩展。此外,由于存在不同的松散耦合组件,每个组件都可以独立于任何其他组件进行伸缩。可伸缩标准:吞吐量、CPU使用率、内存使用率。
注意:自动伸缩配置是构建可伸缩系统的一个重要因素,但在大多数情况下,标准的选择非常重要,CPU,内存的使用不一定是最好的标准。它可以基于并发用户的数量,消息流的数量等。

备注:基于Go语音实现的类似这种框架有Goim:http://goim.io

相关文章

网友评论

      本文标题:如何为直播视频构建大规模消息系统

      本文链接:https://www.haomeiwen.com/subject/yddpprtx.html