如何设计超十万级TPS的im消息沟通系统

前言

如何设计一款高性能,高并发以及高可用的im消息沟通平台是很多公司发展过程中必须要碰到并且解决的问题,如一家公司内部的通信,各个互联网平台的客服咨询,都是离不开一款好用并且方便维护的im消息沟通系统。那么我们应该怎么样来设计一款三高特性的im系统,并能支持各个业务线接入(内部oa通信,客服咨询,消息推送)等功能呢

image.png

下面就由我来介绍一下我所负责im消息沟通系统所经历的设计历程

im第一版设计

im第一版设计的初衷是公司需要一款im消息中间件用于支撑客服咨询业务,但是为了方便日后其他业务线也能接入消息沟通平台,所以将整个消息中心的能力需要给到中间件团队进行开发,各业务线接入消息沟通中心实现消息实时触达的能力

im初版架构介绍

im消息中心初版架构图.jpg

存储端
在存储端我们使用tidb,redis作为主要存储,redis用于存储消息已读未读,缓存连接信息等功能,tidb作为开源的分布式数据库,选择它是为了方便消息的存储

mq消息总线
我们使用rocketmq来实现消息总线,消息总线是整个im的核心,使用rocketmq能支持十万级别的tps。基本所有服务都要从消息总线中消费消息进行业务处理

zookeeper注册中心
服务会注册到zk中,方便服务之间内部进行调用,同样也可以暴露服务给外部进行调用

link服务
link服务主要用于接收客户端的ws,tcp,udp等协议的连接,调用用户服务进行认证,并投递连接成功的消息给位置服务进行消费,存储连接信息。ws过来的消息先到link再投递到消息总线

消息分发服务
消息分发服务主要用于接收消息总线推过来的消息进行处理,按照im内部消息协议构造好消息体后又推送到消息总线中,比如会推给会话服务、消息盒子、link服务

位置服务
存储link的ws连接,tcp连接等信息,并使用redis进行缓存,key为userId,方便根据UserId查询到该用户所登录的客户端连接在哪个link上。一个用户在相同设备只能登录一个,可以多端登录

用户服务
用于存储所有用户,提供认证查询接口

消息盒子
存储所有消息,提供消息查询,消息已读未读,消息未读数,消息检索等功能

会话服务
管理会话,群聊会话,单聊会话等功能

整体流程

im消息中心初版时序图.jpg

该设计存在的问题思考

在上面的架构设计中,我们详细介绍了初版系统架构的设计思路以及具体流程,那么在初版设计中存在什么样的问题,又该如何优化呢?

  • link服务到消息分发服务的消息推送使用消息总线
初版架构设计中,link服务将消息下推给消息分发服务进行处理使用的mq消息总线,使用mq消息总线会有一定的时延。
a用户发送消息到link --> 消息总线 -->消息分发服务 --> 消息总线 --> link --> b用户
这个流程太长,并且大大降低系统吞吐量
  • 消息落库为写扩散
其实现阶段我们使用的微信采用的是写扩散,为啥微信使用写扩散不是缺陷,对于消息沟通中心来说确实缺陷呢?
微信特性:
一、微信号称没有存储用户的聊天记录,全是实时推送
二、微信聊天记录全部会在我们手机端存储一份,两台手机终端上的聊天记录并不互通,并且互不可见
消息沟通中心特性:
一、消息沟通中心是会有拉取历史聊天记录(服务端拉取)的功能,存储了全量消息
二、消息沟通中心不仅要支持客户端版本,还需要支持网页版本,并且很大概率为网页版

综上
1)写扩散对微信这样有客户端版本的即时通讯产品十分友好,每个消息在消息分发的时候给处于这个会话(单聊,群聊)下的所有用户所在客户端先推送消息,
没找到连接就针对这个用户写一个离线缓存消息,那么下次该用户登录进来,可以从缓存中拉取到该消息,并且清掉缓存
2)写扩散对于通用消息沟通平台并不友好,由于接入方大部分是网页版的客户端,所以没有缓存消息的能力,浏览器刷新就没有了任何消息,所以需要实时去
服务端拉取历史消息,假设我是写扩散,在一个群聊中有五百个用户,针对这五百个用户在这个会话,我需要去写五百条消息,大大的增加了写io,并且还不能
写缓存,得写数据库。
  • tidb存在不稳定性,以及事务并发问题
tidb是目前主流的开源分布式数据库,查询效率高,无需分库分表。同样,tidb存在一些隐藏的问题
一、在高并发情况下并发事务会导致事务失败,具体原因不知
二、tidb排错成本高,公司很少有tidb专业运维,经常遇到不走索引的情况
  • 群聊单聊冗余在同一个服务
在初版设计中,单聊和群聊是冗余在会话服务,并且冗余在同一张表的,其实单聊群聊还是会有不同,如业务属性,虽然都是会话,我们还是需要将这两个服务拆分开,细粒度的服务拆分能更好的把控整体的逻辑。

im第二版升级设计

渐渐的我们发现初版im有很大的不足之处,在生产上暴露出了以下问题:

  • tps没达到预期,吞吐量不能满足公司业务的发展
  • 使用的存储中间件难以维护,试错成本高,经常在生产暴露问题,并且速度越来越慢
  • 消息写扩散没有太大必要,并大大增加了系统io次数
  • 一些特性无法支持,比如消息图文检索,消息已读未读

im升级版架构介绍

im消息中心升级版架构图.jpg

存储端
存储端我们使用了mysql,针对消息服务单独使用了主从mysql集群,主节点用于写消息,从节点用于消息检索

mq消息总线
与第一版相比没有改动

link服务
与第一版相比改动了link服务到消息分发服务的消息推送方式(变更为tcp实时推送)

消息分发服务
集成了消息处理能力,路由能力,每台消息分发服务拥有所有link服务的tcp连接

单聊服务
负责单聊会话的管理能力

群聊服务
负责群聊会话的管理能力

用户服务
提供用户认证,登录\注册能力

针对第一版本的改动对比

  • 将link到消息分发服务改为tcp实时连接,百万客户端连接同一台link机器,消息实时触达能力tps达到16万
link到消息分发服务的改版是本次设计的亮点之一
完全消除了mq推送的时延性,并且路由简单,几乎实时触达
用户a --> link --> 消息分发 --> link --> 用户b
link服务到消息分发服务集群的消息推送使用轮询负载均衡的方式,保证公平,不会导致个别机器负载过高
  • 取消位置服务,消息分发服务集成位置服务的能力
消息分发服务本身业务简单,不需要再单独划分位置服务,增加网络io,并且消息分发服务直连link,它负责路由更加方便
  • 存储端使用mysql,增强可维护性,消息服务使用主从读写分离方式,提高消息落库速度与检索速度,减轻数据库压力
前面有提到过使用tidb这样维护成本高,排查问题难的分布式数据库是一件很痛苦的事情,我们使用mysql更加稳定,大家对mysql的学习成本相对较低。针对消息服务使用读写分离的方式,能大大提高消息的吞吐量
  • 实现了特性功能,消息已读未读,红包推送,商品链接推送等功能
新版消息沟通中心加入了消息已读未读,发送红包,链接推送等功能,这些功能带有一定的特性,毕竟不是所有Im都需要,可通过配置取消这些功能
  • 消息存储写扩散改为读扩散
前面有提到,写扩散和读扩散的利弊,对于网页端我们更适合使用读扩散,只需要落一条消息,大大提高消息服务的吞吐量
  • 增加门面服务 im-logic,用于暴露给第三方业务线接口调用
初版都是im的各个服务各自暴露接口给到外部进行调用, 我们统一使用logic服务暴露给外部调用,在logic服务针对调用可以做一些处理,这样不会影响到整体im的通用,不会增加im底层代码的复杂度。将业务逻辑与底层进行解耦

优化效果对比

指标 第一版 第二版
消息实时触达 10000tps 160000tps
全链路tps 5000tps 15000tps
消息推送 6000tps 50000tps

业务线接入im的业务划分思考(以客服系统以及企业微信为例)

假如我开发了一款通用的im消息沟通系统,现在有很多业务方需要接入我们,我们该如何进行业务域的清晰划分显得尤为重要,在妥协与不妥协中进行平衡

当前开源消息沟通平台存在的问题

当前开源的很多消息沟通中心其实是集成了很多的业务逻辑,要不这是一款单纯的客服系统,要不这就是一款好友聊天系统。中间的业务划分并不明确。当然,这也有好处,拿来就能用,并不需要进行二次业务封装。

如何将im设计为一款真正的高性能通用im消息沟通系统

通用的消息沟通平台只需要有通用的底层能力:


im消息中心通用能力图.jpg

以下案例假设在我已经按照上述架构设计了一版im消息沟通中心

客服系统

客服系统接入im.jpg

客服系统不光需要实现自身业务,还需要整合im的消息能力,消费im的消息,来进行场景分析,实现会话变更,信令消息推送等逻辑,客服系统内部需要根据im的底层支持能力进行相应的业务封装以及客服系统的客服用户池,c端用户池如何初始化到im的用户中心这些问题都是需要考虑进去的

内部通信

内部通信接入im.jpg

员工内部通信系统需要集成好友功能,需要根据im的用户中心封装组织架构,用户权限等功能。同时,内部通信系统需要根据im实现消息已读未读,群聊列表,会话列表拉取等功能。

总结

im的消息沟通平台是一款需要高度结合业务的中间件系统,它直接与业务打交道,跟普通的中间件有根本的区别,一款好用的im的消息沟通平台,直接取决于你的通用性,可扩展性以及系统吞吐能力。希望这篇文章能对大家开发im时候的思路有所启迪。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容