5

直播系统聊天技术(六):百万人在线的直播间实时聊天消息分发技术实践

 2 years ago
source link: https://segmentfault.com/a/1190000041236737
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

本文由融云技术团队原创分享,原题“聊天室海量消息分发之消息丢弃策略”,内容有修订。

随着直播类应用的普及,尤其直播带货概念的风靡,大用户量的直播间场景已然常态化。

大用户量直播间中的实时互动是非常频繁的,具体体现在技术上就是各种用户聊天、弹幕、礼物、点赞、禁言、系统通知等实时消息。

如此大量的实时消息,在分发时如何处理才能不至于把服务端搞垮,而到了客户端时也不至于让APP出现疯狂刷屏和卡顿(不至于影响用户体验),这显然需要特殊的技术手段和实现策略才能应对。

其实,直播间中的实时消息分发,在技术上是跟传统的在线聊天室这种概念是一样的,只是传统互联网时代,聊天室同时在线的用户量不会这么大而已,虽然量级不同,但技术模型是完全可以套用的。

本文将基于直播技术实践的背景,分享了单直播间百万用户在线量的实时消息分发的技术经验总结,希望带给你启发。

学习交流:

2、系列文章

本文是系列文章中的第6篇:

《直播系统聊天技术(一):百万在线的美拍直播弹幕系统的实时推送技术实践之路》
《直播系统聊天技术(二):阿里电商IM消息平台,在群聊、直播场景下的技术实践》
《直播系统聊天技术(三):微信直播聊天室单房间1500万在线的消息架构演进之路》
《直播系统聊天技术(四):百度直播的海量用户实时消息系统架构演进实践》
《直播系统聊天技术(五):微信小游戏直播在Android端的跨进程渲染推流实践》
《直播系统聊天技术(六):百万人在线的直播间实时聊天消息分发技术实践》(* 本文)

3、技术挑战

我们以一个百万人观看的直播间为例进行分析,看看需要面临哪些技术挑战。

1)在直播中会有一波一波的消息高峰,比如直播中的“刷屏”消息,即大量用户在同一时段发送的海量实时消息,一般情况下此类“刷屏”消息的消息内容基本相同。如果将所有消息全部展示在客户端,则客户端很可能出现卡顿、消息延迟等问题,严重影响用户体验。

2)海量消息的情况下,如果服务端每条消息都长期存储将导致服务缓存使用量激增,使得内存、存储成为性能瓶颈。

3)在另外一些场景下,比如直播间的房间管理员进行操作后的通知消息或者系统通知,一般情况下这类消息是较为重要的,如何优先保障它的到达率。

基于这些挑战,我们的服务需要做一个基于业务场景的优化来应对。

4、架构模型

我们的架构模型图如下:

如上图所示,下面将针对主要服务进行简要说明。

1)直播间服务:

主要作用是:缓存直播间的基本信息。包括用户列表、禁言/封禁关系、白名单用户等。

2)消息服务:

主要作用是:缓存本节点需要处理的用户关系信息、消息队列信息等。

具体说是以下两个主要事情。

直播间用户关系同步:

a)成员主动加入退出时:直播间服务同步至==> 消息服务;
b)分发消息发现用户已离线时:消息服务同步至==> 直播间服务。

发送消息:

a)直播间服务经过必要校验通过后将消息广播至消息服务;
b)直播间服务不缓存消息内容。

3)Zk(就是 Zookeeper 啦):

主要作用就是:将各服务实例均注册到 Zk,数据用于服务间流转时的落点计算。

具体就是:

a)直播间服务:按照直播间 ID 落点;
b)消息服务:按照用户 ID 落点。

4)Redis:

主要作为二级缓存,以及服务更新(重启)时内存数据的备份。

5、消息分发总体方案

直播间服务的消息分发完整逻辑主要包括:消息分发流程和消息拉取流程。

5.1 消息分发流程

如上图所示,我们的消息分发流程主要是以下几步:

1)用户 A 在直播间中发送一条消息,首先由直播间服务处理;
2)直播间服务将消息同步到各消息服务节点;
3)消息服务向本节点缓存的所有成员下发通知拉取;
4)如上图中的“消息服务-1”,将向用户 B 下发通知。
另外,因为消息量过大,我们在在分发的过程中,是具有通知合并机制的,通知合并机制主要提现在上述步骤 3 中。

上述步骤3的通知合并机制原理如下:

a)将所有成员加入到待通知队列中(如已存在则更新通知消息时间);
b)下发线程,轮训获取待通知队列;
c)向队列中用户下发通知拉取。
通过通知合并机制,我们可以可保障下发线程一轮只会向同一用户发送一个通知拉取,即多个消息会合并为一个通知拉取,从面有效提升了服务端性能且降低了客户端与服务端的网络消耗。

PS:以上通知合并机制,在大消息量的情况下,非常适合使用Actor分布式算法来实现,有兴趣的同学可以进一步学习《分布式高并发下Actor模型如此优秀》、《分布式计算技术之Actor计算模式》。

5.2 消息拉取流程

如上图所示,我们的消息拉取流程主要是以下几步:

1)用户 B 收到通知后将向服务端发送拉取消息请求;
2)该请求将由“消息服务-1”节点处理;
3)“消息服务-1”将根据客户端传递的最后一条消息时间戳,从消息队列中返回消息列表(原理详见下图 ▼);
4)用户 B 获取到新的消息。
上述步骤 3 中拉取消息的具体逻辑如下图所示:

6、消息分发的丢弃策略

对于直播间中的用户来说,很多消息其实并没有太多实际意义,比如大量重复的刷屏消息和动态通知等等,为了提升用户体验,这类消息是可以有策略地进行丢弃的(这是跟IM中的实时聊天消息最大的不同,IM中是不允许丢消息的)。

PS:直播间中消息分发的丢弃策略,跟上节中的通知合并机制一起,使得直接间海量消息的稳定、流畅分发得以成为可能。

我们的丢弃策略主要由以下3部分组成:

1)上行限速控制(丢弃)策略;
2)下行限速控制(丢弃)策略;
3)重要消息防丢弃策略。

如下图所示:

我们来逐个解释一下。

1)上行限速控制(丢弃)策略:

针对上行的限速控制,我们默认是 200 条/秒,根据业务需要可调整。达到限速后发送的消息将在直播间服务丢弃,不再向各消息服务节点同步。

2)下行限速控制(丢弃)策略:

针对下行的限速控制,即对消息环形队列(见“5.2 消息拉取流程”中的拉取消息详细逻辑图)长度的控制,达到最大值后最“老”的消息将被淘汰丢弃。

每次下发通知拉取后服务端将该用户标记为“拉取中”,用户实际拉取消息后移除该标记。

拉取中标记的作用:例如产生新消息时用户具有拉取中标记,如果距设置标记时间在 2 秒内则不会下发通知(降低客户端压力,丢弃通知未丢弃消息),超过 2 秒则继续下发通知(连续多次通知未拉取则触发用户踢出策略,不在此赘述)。

因此消息是否被丢弃取决于客户端拉取速度(受客户端性能、网络影响),客户端及时拉取消息则没有被丢弃的消息。

3)重要消息防丢弃策略:

如前文所述:在直播间场景下对某些消息应具有较高优先级,不应丢弃。

例如:直播间的房间管理员进行操作后的通知消息或者系统通知。

针对此场景:我们设置了消息白名单、消息优先级的概念,保障不丢弃。如本节开始的图所示,消息环形队列可以为多个,与普通直播间消息分开则保障了重要消息不丢弃。

通过上述“1)上行限速控制(丢弃)策略”和“下行限速控制(丢弃)策略”保障了:

1)客户端不会因为海量消息出现卡顿、延迟等问题;
2)避免出现消息刷屏,肉眼无法查看的情况;
3)同时降低了服务端存储压力,不会因为海量消息出现内存瓶颈从而影响服务。

7、写在最后

随着移动互联网的发展,直播间的实时消息业务模型和压力也在不停地扩展变化,后续可能还会遇到更多的挑战,我们的服务会与时俱进、跟进更优的方案策略进行应对。

附录:多人群聊天技术文章

[1]《IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?》
[2]《IM群聊消息如此复杂,如何保证不丢不重?》
[3]《移动端IM中大规模群消息的推送如何保证效率、实时性?》
[4]《现代IM系统中聊天消息的同步和存储方案探讨》
[5]《关于IM即时通讯群聊消息的乱序问题讨论》
[6]《IM群聊消息的已读回执功能该怎么实现?》
[7]《IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)?》
[8]《一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践》
[9]《IM群聊机制,除了循环去发消息还有什么方式?如何优化?》
[10]《网易云信技术分享:IM中的万人群聊技术方案实践总结》
[11]《阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处》
[12]《IM群聊消息的已读未读功能在存储空间方面的实现思路探讨》
[13]《企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等》
[14]《融云IM技术分享:万人群聊消息投递方案的思考和实践》

(本文已同步发布于:http://www.52im.net/thread-37...


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK