乐趣区

关于即时通讯:im即时通讯开发群消息推送如何保证实时性

众所周之,群聊是挪动端 IM 的服务端技术难点所在,难在哪?大量的群聊音讯,是一条条推给群内成员还是能够应用什么样的优化策略?试想一个 2000 人大群,一条音讯的收回,如果霎时被扩散写成 2000 条一对一音讯的投递,对于接管方而言不过是一条音讯而已,而服务端是以对绝对比单聊音讯的 2000 倍解决压力后的后果。那么服务端在保障音讯投递的同时,面对这么大的压力该如何解决好效率问题?解决不好效率问题那实时性就不能保障!

当然,理论在生产环境下,群音讯的发送都会想尽办法进行压缩,并发展各种改善性能的解决方法,而不是像上述举例里的间接扩散写(即 2000 人群里,一条音讯被简略地复制为 2000 条一对一的音讯投递)。

先大抵剖析一下问题产生的起因。

1)音讯量霎时大增:

抢红包时大家都比拟沉闷,不停在群里发消息,尤其群成员比拟多的群(500 人),每条音讯都会给服务端带来大量的计算工作。

2)后盾逻辑不够优化:

比方红包音讯没有独自的通道,时效性会收到其余音讯影响、没有采纳批处理形式、异步解决有些环节还不到位等等。即时通讯聊天软件开发能够征询蔚可云。

精确定位问题的起因

咱们尝试精确定位问题的根本原因,起因剖析如下。

1)c2g 模块没有采取批处理形式:

1 条群(500 人群)音讯达到 c2g 模块后,c2g 模块为每个人写收件箱(这里时间延迟较大,优化点),而后在把这条音讯变成 500 条投递音讯(须要批处理,就给 Kafka 放入一条音讯),通过 Kafka 送给 Deliver 节点投递。

2)Deliver 模块的解决没有批量合并:

Deliver 模块会到 Redis 中逐条(500 条)检索接管音讯用户的在线状态(这个点须要批处理,依据用户 Id 散布,一次检索若干用户的在线状态),在线的投递音讯(批处理),离线的发送第三方 push(批处理)。

3)离线推送流程不优化:

整体流程上,每条音讯是先写了离线收件箱,再推送。这样效率也不高,须要对这个流程细化以及异步化。

总结一下就是:

微信在这块的一个重要优化思维是批处理,做法是单次批量操作(咱们本次优化指标)裸写,多条音讯的聚合(MapReduce 过程)下沉到了 MQ 中间件中。

群聊红包逻辑独自部署

现阶段,当音讯(尤其是大群音讯)量大的时候,Deliver 节点会成为瓶颈。红包对时效性要求很高,架构上采纳独立为红包部署 Deliver 节点的形式确保红包音讯走独自通道进行推送。即便其余音讯呈现提早,红包音讯仍然能保障即便送达。

裸写批处理逻辑

解决一条群音讯,服务端要进行大量的工作,须要查问所有群成员的路由表、在线状态,在线人员须要推送及时音讯,离线人员须要推送第三方 push(比方 iOS 的 apns 推送通道)。这些工作逐条执行,性能会十分差,如果遇到大群,零碎会不可用。

批处理能够较好解决这个问题。比方用户状态及路由表数据,采纳 hash 算法散布在几台服务器上。收到群音讯后,依据群成员,计算出用户状态及路由表数据的散布状况,从缓存服务器中一次检索出该服务器可能存在的所有群成员状态及路由信息。这样能够极大缩小 RPC 调用次数,及计算量。

推送操作也相似,批量向接入层投递音讯即可。

离线音讯异步写收件箱

在解决大群音讯推送时,写离线音讯也是一个十分影响性能的中央。现有的逻辑是先为每个人写一条离线音讯,再执行推送。

1)Deliver 节点收到一条群音讯,检索用户在线状态及路由信息,用户在线(离线的逻辑绝对简略,略过);

2)批量推送音讯(2、批处理逻辑);

3)异步将音讯写入音讯总线,同时写入第三方 push 的提早推送工作;

4)异步写离线音讯(不影响在线用户收到音讯的速度);

5)第(2)步推送音讯的 ack 信息回到服务端;

6)c2g 模块将 ack 信息放入音讯总线。(确保音讯时序性,ack 须要在写离线音讯之后解决,否则可能呈现音讯反复);

7)删除对应的离线音讯;

8)第(3)步写入的提早推送工作,在规定工夫(如 10 秒)后失效,判断是否存在此条离线音讯(如果 ack 回来了,离线音讯会被删掉),如果离线音讯还存在,发送第三方 push。

通过以上 3 个方面的优化,可能确保在并发音讯量较大时,推送音讯仍然及时。

退出移动版