要实现一整套能用于大用户量、高并发场景下的IM群聊,技术难度远超IM系统中的其它功能,原因在于:IM群聊消息的实时写扩散特性带来了一系列技术难题。

举个例子:如一个2000人群里,一条普通消息的发出问题,将瞬间写扩散为2000条消息的接收问题,如何保证这些消息的及时、有序、高效地送达,涉及到的技术问题点实在太多,更别说个别场景下万人大群里的炸群消息难题了更别说个别场景下万人大群里的炸群消息难题了。

这也是为什么一般中大型IM系统中,都会将群聊单独拎出来考虑架构的设计,单独有针对性地进行架构优化,从而降低整个系统的设计难度。

所谓的群聊消息系统,就是一种多对多群体聊天方式,譬如直播房间内的聊天室对应的服务器端就是一个群聊消息系统。

系统名词解释:

1)Client : 消息发布者【或者叫做服务端群聊消息系统调用者】,publisher;

2)Proxy :系统代理,对外统一接口,收集Client发来的消息转发给Broker;

3)Broker :系统消息转发Server,Broker 会根据 Gateway Message 组织一个 RoomGatewayList【key为RoomID,value为 Gateway IP:Port 地址列表】,然后把 Proxy 发来的消息转发到 Room 中所有成员登录的所有 Gateway;

4)Router :用户登录消息转发者,把Gateway转发来的用户登入登出消息转发给所有的Broker;

5)Gateway :所有服务端的入口,接收合法客户端的连接,并把客户端的登录登出消息通过Router转发给所有的Broker;

6)Room Message : Room聊天消息;

7)Gateway Message : Room内某成员 登录 或者 登出 某Gateway消息,包含用户UIN/RoomID/Gateway地址{IP:Port}等消息。

当一个 Room 中多个 Client 连接一个 Gateway 的时候,Broker只会根据 RoomID 把房间内的消息转发一次给这个Gateway,由Gateway再把消息复制多份分别发送给连接这个 Gateway 的 Room 中的所有用户的客户端。

这套系统有如下特点:

1)系统只转发房间内的聊天消息,每个节点收到后立即转发出去,不存储任何房间内的聊天消息,不考虑消息丢失以及消息重复的问题;

2)系统固定地由一个Proxy、三个Broker和一个Router构成;

3)Proxy接收后端发送来的房间消息,然后按照一定的负载均衡算法把消息发往某个Broker,Broker则把消息发送到所有与Room有关系的接口机Gateway;

4)Router接收Gateway转发来的某个Room内某成员在这个Gateway的登出或者登录消息,然后把消息发送到所有Broker;

5)Broker收到Router转发来的Gateway消息后,更新(添加或者删除)与某Room相关的Gateway集合记录;

6)整个系统的通信链路采用UDP通信方式。

从以上特点,整个消息系统足够简单,没有考虑扩缩容问题,当系统负载到达极限的时候,就重新再部署一套系统以应对后端client的消息压力。

这种处理方式本质是把系统的扩容能力甩锅给了后端Client以及前端Gateway:每次扩容一个系统,所有Client需要在本地配置文件中添加一个Proxy地址然后全部重启,所有Gateway则需要再本地配置文件添加一个Router地址然后全部重启。

这种“幸福我一人,辛苦千万家”的扩容应对方式,必然导致公司内部这套系统的使用者怨声载道,下一阶段的升级就是必然的了。

接下来迫切要解决的:系统稳定性

系统具有了可扩展性仅仅是系统可用的初步,整个系统要保证最低粒度的SLA(0.99),就必须在两个维度对系统的可靠性就行感知:消息延迟和系统内部组件的高可用。

消息延迟

准确的消息延迟的统计,通用的做法可以基于日志系统对系统所有消息或者以一定概率抽样后进行统计,但限于人力目前没有这样做。

目前使用了一个方法:通过一种构造一组伪用户ID,定时地把消息发送给proxy,每条消息经过一层就把在这层的进入时间和发出时间以及组件自身的一些信息填入消息,这组伪用户的消息最终会被发送到一个伪Gateway端,伪Gateway对这些消息的信息进行归并统计后,即可计算出当前系统的平均消息延迟时间。

通过所有消息的平均延迟可以评估系统的整体性能。同时,因为系统消息路由的哈希方式已知,当固定时间内伪Gateway没有收到消息时,就把消息当做发送失败,当某条链路失败一定次数后就可以产生告警了。

高可用

上面的方法同时能够检测某个链路是否出问题,但是链路具体出问题的点无法判断,且实时性无法保证。

为了保证各个组件的高可用,系统引入了另一种评估方法:每个层次都给后端组件发送心跳包,通过心跳包的延迟和成功率判断其下一级组件的当前的可用状态。

譬如proxy定时给每个Partition内每个broker发送心跳,可以依据心跳的成功率来快速判断broker是否处于“假死”状态(最近业务就遇到过broker进程还活着,但是对任何收到的消息都不处理的情况)。

同时依靠心跳包的延迟还可以判断broker的处理能力,基于此延迟值可在同一Partition内多broker端进行负载均衡。

进一步优化:消息可靠性

公司内部内部原有一个走tcp通道的群聊消息系统,但是经过元旦一次大事故(几乎全线崩溃)后,相关业务的一些重要消息改走这套基于UDP的群聊消息系统了。这些消息如服务端下达给客户端的游戏动作指令,是不允许丢失的,但其特点是相对于聊天消息来说量非常小(单人1秒最多一个),所以需要在目前UDP链路传递消息的基础之上再构建一个可靠消息链路。

UDP通信的本质就是伪装的IP通信,TCP自身的稳定性无非是重传、去重和ack,所以不考虑消息顺序性的情况下可以通过重传与去重来保证消息的可靠性。即时通讯开发

基于目前系统的可靠消息传输流程如下:

1)Client给每个命令消息依据snowflake算法配置一个ID,复制三份,立即发送给不同的Proxy;

2)Proxy收到命令消息以后随机发送给一个Broker;

3)Broker收到后传输给Gateway;

4)Gateway接收到命令消息后根据消息ID进行重复判断,如果重复则丢弃,否则就发送给APP,并缓存之。

正常的消息在群聊消息系统中传输时,Proxy会根据消息的Room ID传递给固定的Broker,以保证消息的有序性。

当线上需要部署多套群聊消息系统的时候,Gateway需要把同样的Room Message复制多份转发给多套群聊消息系统,会增大Gateway压力,可以把Router单独独立部署,然后把Room Message向所有的群聊消息系统转发。

Router系统原有流程是:Gateway按照Room ID把消息转发给某个Router,然后Router把消息转发给下游Broker实例。新部署一套群聊消息系统的时候,新系统Broker的schema需要通过一套约定机制通知Router,使得Router自身逻辑过于复杂。

类似于Broker,Router Partition也以2倍扩容方式进行Partition水平扩展,并通过一定机制保证扩容或者Partition内部各个实例停止运行或者新启动时,尽力保证数据的一致性。

Router Replica收到Gateway Message后,replica先把Gateway Message转发给Partition内各个peer replica,然后再转发给各个订阅者。Router转发消息的同时异步把消息数据写入Database。

im即时通讯开发:高可用、易伸缩、高并发的IM群聊、单聊架构方案设计相关推荐

  1. Android 即时通讯开发小结(二)

    <Android 即时通讯开发小结>基于IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,对 IM 开发做一个全面的总结. 相关推荐阅读:. Android即时通讯 ...

  2. Android 即时通讯开发小结(一)

    本文将基于 IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,对 IM 开发做一个全面的总结. 客户端架构 作为一个 IM 软件,最重要的一个特性就是保证消息的达到率和实时性. ...

  3. im即时通讯开发之后台应用保活、消息推送的噩梦

    Android P的最后一个开发者预览版(即DP5)已如期发布于2018年7月26日,根据上面这张发布路线图,相信Android P的正式版将很快到来.对于Andriod开发者来说,不管Andriod ...

  4. im即时通讯开发:移动端需要面对的问题

    统一介绍下一个IM APP的方方面面,包括技术选型(包括通讯方式,网络连接方式,协议选择)和常见问题. P2P还是服务器中转? IM通讯方式无非两种选择:设备直连(P2P)和通过服务器中转. 1P2P ...

  5. im即时通讯开发:群聊消息如此复杂,如何保证不丢不重

    群聊已经成为主流IM软件的基本功能,不管是QQ群.还是微信群,一个群友在群内发了一条消息,那么对于IM服务器来说需要保证: 在线的群友能第一时间收到消息: 离线的群友能在登陆后收到消息. 常见的群消息 ...

  6. 盘点im即时通讯开发中Android后台保活方案

    对于IM应用和消息推送服务的开发者来说,在Android机型上的后台保活是个相当头疼的问题. 老板一句:"为什么微信.QQ能收到消息,而你写的APP却不行?",直接让人崩溃,话说老 ...

  7. 即时通讯开发如何构建一套移动端消息推送系统

    消息推送作为移动端 APP 运营中的一项关键技术,已经被越来越广泛的运用. 本文追溯了推送技术的发展历史,剖析了其核心原理,并对推送服务的关键技术进行深入剖析,围绕消息推送时产生的服务不稳定性,消息丢 ...

  8. 谈谈即时通讯开发平台

    由于即时通讯系统的复杂性和对服务器稳定性的很高要求,一般即时通讯系统开发至少需要1年左右的时间,而这还只是测试版,离"稳定"还有一定距离,而这时匆匆上马的不稳定的系统会让你失去用户 ...

  9. 基于Netty实现分布式IM即时通讯开发

    计算机编程的学习,能不能把知识学到手,讲究的是动手实践.在我编写的文章中,基本都是以实践代码验证结果为核心来讲述文章内容. 可能有人不知道 Netty 是什么,这里简单介绍下: Netty 是一个 J ...

最新文章

  1. crt 运行时库dll跨模块传递crt对象,出现的崩溃问题
  2. 可扩展且侵入性最小的脑机接口平台
  3. 联想e52进入bios_联想笔记本怎么设置u盘启动|联想笔记本bios设置usb启动步骤
  4. Windows系统下安装分布式事务组件Seata
  5. 如何设置Windows版Go —快速简便的指南
  6. 关于Const指针的一点补充
  7. seriespandas索引操作练习
  8. 面向对象闲话(一)——什么是对象
  9. 有关分组、帧、报文、比特流的问题
  10. c语言单片机题目设计大全,51单片机毕业设计题目.docx
  11. 《别闹了,费曼先生》
  12. conan入门(六):conanfile.txt conanfile.py的区别
  13. 计算机excel混合引用,Excel2019中单元格的三种引用方式
  14. Fabric v2.2 单机部署 使用tape测试
  15. 短视频代运营服务内容
  16. 理解Python中的RingBuffer环形缓冲区
  17. 5393: YuYu的密码II
  18. python3爬取头条比基尼图片
  19. 【SVG】svg入门
  20. 改进排队买票多线程问题

热门文章

  1. 海尔简爱s11怎么进入bios_海尔简爱s11系统应用商店没有登录界面怎么办?
  2. 微信公众号官方API开发之配置服务器
  3. pta中java编程题_多文件编程题
  4. 如何判断一个点在多边形内
  5. 从零开始的前端—HTML 02
  6. 如何在 Python 中构建跨平台桌面应用程序
  7. 简易的监控mysql_使用开源工具mysqlreport监控Mysql数据库-简易使用方法
  8. 武汉大学 遥感院 数据结构实习
  9. 传销式招聘!被骗到东南亚的程序员到底有多惨?
  10. 手机链游撼动腾讯王者荣耀?Nova Battles更具潜力