Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【原创】开源OpenIM:高性能、可伸缩、易扩展的即时通讯架构

【原创】开源OpenIM:高性能、可伸缩、易扩展的即时通讯架构

原创
作者头像
OpenIM
修改于 2021-07-28 10:03:17
修改于 2021-07-28 10:03:17
2.3K00
代码可运行
举报
文章被收录于专栏:IM即时通讯技术IM即时通讯技术
运行总次数:0
代码可运行

开源OpenIM:高性能、可伸缩、易扩展的即时通讯架构

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
本文属于OpenIM技术团队原创,转载请注明出处,谢谢

网上有很多关于IM的教程和技术博文,有亿级用户的IM架构,有各种浅谈原创自研IM架构,也有微信技术团队分享的技术文章,有些开发者想根据这些资料自研IM。理想很丰满,现实很骨感,最后做出来的产品很难达到商用标准。事实上,很多架构没有经过海量用户的考验,当然我们也不会评判某种架构的好坏,如果开发者企图根据网上教程做出一个商用的IM,可能有点过于乐观了。本文主要从我个人角度深度剖析100%开源的OpenIM架构。当然,世界上没有最完美的架构,只有最合适的架构,也没有所谓的通用方案,不同的解决方案都有其优缺点,只有最满足业务的系统才是一个好的系统。而且,在有限的人力、物力,综合考虑时间成本,通常需要做出很多权衡。我们OpenIM的设计初衷,充分考虑了中小企业的需求,轻量级部署,同时也支持集群扩展,能支持几万用户,也能轻松扩展到上亿用户,是一个可信赖的开源项目。

IM系统技术挑战

可靠性

IM消息系统的可靠性,通常就是指消息投递的可靠性,即我们经常听到的“消息必达”,通常用消息的不丢失和不重复两个技术指标来表示。确保消息被发送后,能被接收者收到。由于网络环境的复杂性,以及用户在线的不确定性,消息的可靠性(不丢失、不重复)无疑是IM系统的核心指标,也是IM系统实现中的难点之一。总体来说,IM系统的消息“可靠性”,通常就是指聊天消息投递的可靠性(准确的说,这个“消息”是广义的,因为还存用户看不见的各种指令和通知,包括但不限于进群退群通知、好友添加通知等,为了方便描述,统称“消息”)。

从消息发送者和接收者用户行为来讲,消息“可靠性”应该分为以下几种情况:

(1)发送失败,对于这种情况IM系统必须要感知到,明确反馈发送方。如果此消息没有发送成功,发送方可以选择重试或者稍后再试。

(2)发送成功,如果接收方处在“在线”状态,应该立即收到此消息。如果接收方处在“离线”状态不能收到消息,一旦上线则立刻收到消息。

(3)消息不能重复,用数学术语表示:“有且仅有这条消息”,如果重复了,可能表达的意思就变了。 总之,一个商用 IM系统,必须包含消息“可靠性”逻辑,才能谈基本可用,这是IM系统最基本也是最核心的逻辑。

有序性(一致性)

IM系统中,特别需要考虑消息时序问题,如果后发送的消息先显示,可能严重扰乱聊天消息所要表达的意义,会造成聊天语义不连贯,引起误会。消息的时序性,也称为消息收发一致性,主要目标是:保证聊天消息的绝对时序。IM系统中消息时序的一致性问题看似简单,实则是非常有难度的技术热点话题之一。为什么会出现时序问题 1、分布式系统的出现导致时序不一致。IM系统模块众多,接入层、消息逻辑层等、每层都分布式集群化,这些应用分布在不同的机器上,如何保证时序是个难点。2、网络传输延迟导致时序不一致。不同用户发送的消息到达服务器的延时差异较大,给消息时序性带来挑战。

消息时序是分布式系统架构设计中非常难的问题,一个分布式的IM系统必须要解决这个问题,如何高效、低成本解决这个问题,是我们OpenIM要考虑的方向。

实时性

实时性,即消息实时到达接收方,如果用户在线,则实时可达,如果用户不在线,则登录时可达。由于网络波动,以及移动端操作系统对应用前后台切换的管理,如何实现用户连接管理、消息实时推送,推送失败的处理方式,客户端重连机制,消息如何补齐等,都是需要IM系统考虑,同时要结合移动端的特点,兼顾耗电量,网络,性能等。由于TCP开发略微复杂,早期的基于HTTP短轮询、长轮询的低效的技术方案,也无法达到实时性的要求。

扩展性

一般来说互联网系统的扩展性包含多个含义,我们侧重讲解关于IM消息的扩展性。IM业务特性多,功能丰富,从聊天类型来看,分为:单聊、群聊,聊天室等;从消息类型来看,分为:文本、图片、视频、地理位置、自定义消息等;从消息功能来看,分为:撤回、在线状态、对方正在输入、阅后即焚等;从通知角度来看,分为:进群、退群、添加好友、验证好友等各种通知。如何有效支撑、扩展功能,高效实现,是考验IM扩展性的一个方面,也是对系统架构设计能力的考验。为了更好地提高数据通道对业务支撑的扩展性,我们首创了“一切皆消息”的消息模型,即通讯双方产生的所有消息、通知,服务端以消息统一处理,扮演了消息通道的角色,客户端针对不同消息类型做不同的UI展示,完美解决了扩展性问题。

IM系统术语以及本文档专有名词解释

conversationId:会话Id,会话是指用户和用户之间,以及用户和群之间,进行通讯后产生的关联。

userId:用户Id:注册使用IM的用户Id,从消息的发送和接收来看有两个身份:发送者和接收者

sendId:消息发送者Id

receiverId :消息接收者Id

msg:消息是指用户之间的沟通内容,一般指用户主动产生的。同时也包括用户看不见的各种指令和通知,包括但不限于进群退群通知、好友添加通知等

inbox:用户收件箱,给某人发送消息,实际上是往接收者“信箱”写入消息,这个信箱就是收件箱

seq:用户收件箱中消息序列号,分为local seq,和server seq,前者表示app本地消息seq,后者表示服务端消息seq,seq是连续且递增的。

conn:登录用户的连接信息,用于消息推送;

MQ:消息队列,一般用来解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性架构,本文采用kafka组件。

OpenIM的诞生

随着移动互联网的蓬勃发展, IM 作为一种通讯能力,已经成为互联网上的基础设施,也是许多 APP 不可或缺的功能。如何让每一个应用都具备IM功能,同时考虑企业的接入成本、服务器资源以及最重要的数据安全性和私密性。本人从微信离职后,创办了开源OpenIM,是全球首家100%开源、免费项目,并提供IMSDK,覆盖所有主流开发平台,iOSAndroidFlutter、react native、WindowsLinux、Unity、web、小程序等。

开源IM现状

github 上 IM 开源项目不少,但开发者却难以使用,主要有几点原因(1)个人项目居多,但近几年都无人维护,遇到问题无人解决,企业商业化产品不敢冒险使用(2)大部分项目不是 IM 技术专业团队完成的,技术实力和技术架构存疑,也没有经过大项目和海量用户检验;(3)只开源服务端或者客户端,只开源某一端,需要开发者实现另外一端,研发成本同样不小,另外,开源项目大部分都是以聊天app形式开源,开发者如何把 IM 集成到自身 app 中,同样存在大量的修改和适配成本。(4)部分项目打着开源的旗号,社区版免费,但核心功能缺失,商业版收费。

云服务商的弊端

IM 云服务商提供 IM SDKAPI ,让开发者简单集成 IM 功能,当然这里也存在明显的问题(1)成本问题:企业每年额外支付上万乃至数十万的云服务费用,从长期来看是个不小的成本;(2)数据隐私问题:企业的用户数据、聊天记录等核心数据托管在 IM 云服务商,如何保证客户的数据隐私和安全性;(3)需求定制问题:IM 需求多样化,IM 功能只能由 IM 云服务商通过 SDK 的形式提供给大家使用,开发受限,所有功能都需要封装成接口;(4)捆绑问题:一旦使用 IM 云服务,形成捆绑关系,迁移成本高,受制于人。

自研的尴尬

IM 是一个看起来门槛很低的项目,网上有很多所谓的 IM 开发教程,甚至很多毕业设计也是做一个 IM 系统。由于这个误区的存在,很多企业盲目乐观组建 3-5 人的 IM 团队,历时一年半载,最后只完成了一个 demo 版本。由于架构设计不合理,demo 版本存在消息丢失、系统异常等 bug,无法达到商用的要求。IM系统除了面临互联网业务系统本身的挑战,还存在上文分析的可靠性、时序性、扩展性等问题,所以,自研IM,对于中小企业来说,可能是最糟糕的选择。

OpenIM的整体架构

OpenIM分为两大块

(一)Open-IM-SDK-Core 采用golang实现客户端逻辑,主要负责本地db存储及更新;断网重连及管理;消息及各种通知回调。本地消息、会话等数据存储,通过通知机制完成本地数据实时同步,同时兼顾客户端缓存的作用,有效缓解了服务端压力。另外,golang跨平台的特性,使得各移动平台都能无缝调用,开发者只需根据产品需求编写UI界面,通过回调机制和SDK完成数据交互和通知。

(二)Open-IM-Server 由接入层、逻辑层和存储层组成,好处在于各层能够依据业务特点专注于自己的事情,提高系统复用性,降低业务间的耦合。

(1)接入层:消息通过 websocket 协议接入,其他业务通过 http/https 协议提供REST API实现。消息是高频及核心功能,通过双协议路由,体现了轻重分离的设计思想。

(2)逻辑层:通过 rpc 实现无状态逻辑服务,易于平行扩展,模块通过 MQ 解耦。

(3)存储层:redis 存储 token 和 seq;mongodb 存储离线消息,并定时删除 14 天内(可自行配置)数据;mysql 存储全量历史消息以及用户相关资料。数据分层存储,充分利用不同存储组件的特性。

(4)Etcd:服务注册和发现、以及分布式配置中心

消息网关msg_gateway

消息接入层,采用websocket协议接入,import gorilla具体实现,服务模块无状态,柔性伸缩,运维简单。通过MQ让业务模块之间解耦,消息写入MQ即表示发送成功。

(1)负责用户连接管理,保持长连接,存储uid->conn映射关系;

(2)负责消息接收落地,成功写入MQ后给客户端返回成功;

(3)负责把消息推送给在线状态的接收者;

下图是客户端发送消息流程

消息转发msg_transfer

消息处理rpc,作为消费者从MQ中消费(读取)消息,递增接收者收件箱seq,关联seq和msg,并存储到mongodb。全量历史消息无收件箱概念,消息作为流水记录落地mysql即可,两者通过协程独立处理,双方互不影响。msg作为无状态服务节点,如果消息量增加,可以启动冗余节点服务,加快消息处理流程。

(1)负责消费MQ中的消息,作为消费者,实时感知新信息达到,并触发回调逻辑;

(2)生成msgId作为全局消息Id;

(3)读取receiver userId,并通过redis的incr操作递增服务端对应的seq;

(4)关联seq和msgid,并存入以receiver userid为key的mongodb中,作为离线消息,一般在14天后会删除;

(5)同时,把消息作为历史记录存入mysql中,作为消息备份,或其他用途。

(4)和(5)是两个独立的协程并行执行的,mysql写入快慢不会影响mongodb的写入,这样既完成了冷热数据分离,也充分利用了机器资源。

下图是消息处理入库流程

消息推送push

msg_transfer完成存储消息到后,向push发起消息推送任务,msg_gateway查询本地userId->conn表,如果用户在线则推送给接收者,对于msg_gateway的推送架构设计,做成了“半状态”服务,即在节点本地存储了用户连接信息,作为局部信息,没有通过redis全局共享。push推送消息时,向所有msg_gateway发送推送请求,带来一定的“惊群效应”,由于msg_gateway节点不多,所以影响有限,带来的好处则是在不影响性能的前提下,msg_gateway设计和实现简单,运维也更简单。

(1)msg_transfer把消息写入mongodb后,发送push消息推送请求;

(2)push提供rpc推送服务,通过etcd找到所有注册的msg_gateway,并发送推送请求;

(3)msg_gateway从本节点内存中查询userId->conn,如果找到conn,则向客户端推送消息;

(4)如果消息接收者不在线,msg_gateway无法推送消息,但客户端网络重连时会及时同步历史消息,进行消息补齐;

下图是消息实时推送流程:

消息同步及对齐seq

由于网络的波动以及负责的网络环境,导致消息推送存在不确定性。OpenIM采用local seq和server seq消息对齐,同时结合拉取和推送的方式,简单高效地解决了消息的可靠性问题。这里分两种场景进行表述:

(1)客户端接收推送消息时,比如客户端收到推送消息的seq为100,如果local seq为99,因为seq递增且连续,所以消息正常显示即可。如果local seq大于100,说明重复推送了消息,抛弃此消息即可。如果local seq小于99,说明中间有历史消息丢失,拉取(local seq+1, 100)的消息,进行补齐即可;

(2)用户在登录、或者断网重连时,客户端会从服务端拉取最大seq(max seq),读取客户端本地seq(local seq),如果local seq 小于 max seq,说明存在历史消息未同步的情况,调用接口同步自身收件箱[local seq+1, max seq]的数据完成消息对齐。

下图是消息同步流程图

本文主要简单阐述了OpenIM的架构以及消息流程,让开发者对其有初步认识,在接下来的文章中,我们会详细讲解OpenIM服务端消息架构,OpenIM客户端架构,同时会详细分析OpenIM如何简单高效解决消息的可靠性、实时性、一致性和扩展性问题。

更多阅读

基于Tablestore Timeline的IM(即时通讯)消息系统架构 - 架构篇

OpenIM官网

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
通俗易懂 即时通讯初学者入门 WhatsApp技术架构
Open-IM是由前微信技术专家打造的开源的即时通讯组件。Open-IM包括IM服务端和客户端SDK,实现了高性能、轻量级、易扩展等重要特性。开发者通过集成Open-IM组件,并私有化部署服务端,可以将即时通讯、实时网络能力快速集成到自身应用中,并确保业务数据的安全性和私密性。
用户8964349
2021/09/22
2.1K0
通俗易懂 即时通讯初学者入门 WhatsApp技术架构
【架构设计】高并发IM系统架构优化实践
作者简介: 少强,网名无衣蒹葭,阿里云资深工程师,主要做分布式存储和搜索相关的工作。 摘要: 介绍如何设计一个稳定、高并发、消息保序的IM系统,以及如何通过使用存储层的高级功能来优化系统架构。 在构建社交IM和朋友圈应用时,一个基本的需求是将用户发送的消息和朋友圈更新及时准确的更新给该用户的好友。为了做到这一点,通常需要为用户发送的每一条消息或者朋友圈更新设置一个序号或者ID,并且保证递增,通过这一机制来确保所有的消息能够按照完整并且以正确的顺序被接收端处理。当消息总量或者消息发送的并发数很大的时候,我们通
数据和云
2018/03/07
2.2K0
【架构设计】高并发IM系统架构优化实践
开源即时通讯(IM)项目OpenIM源码部署流程
由于OpenIM依赖的组件较多,开发者需求不一,导致OpenIM部署一直被人诟病,经过几次迭代优化,包括依赖的组件compose的一键部署,环境变量设置一次,全局生效,以及脚本重构,目前OpenIM部署比较丝滑,特写文章分享给大家。
OpenIM
2023/09/12
2.2K0
一个海量在线用户即时通讯系统(IM)的完整设计
移动端重点是移动端,支持IOS/Android系统,包括IM App,嵌入消息功能的瓜子App,未来还可能接入客服系统。
普通程序员
2019/10/23
3.3K0
一个海量在线用户即时通讯系统(IM)的完整设计
一个海量在线用户即时通讯系统(IM)的完整设计Plus
《一个海量在线用户即时通讯系统(IM)的完整设计》(以下称《完整设计》)这篇文章发出来之后有不少读者咨询问题,提出意见或建议。主要集中在模块拆分、协议、存储等方面。针对这些问题做个简单说明。
Criss@陈磊
2019/08/02
5.8K0
原创分布式即时通讯(IM)系统理论架构方案
无论是IM消息通信系统还是客户消息系统,其本质都是一套消息发送与投递系统,或者说是一套网络通信系统,其本质两个词:存储与转发。
烂猪皮
2020/09/01
1.7K0
原创分布式即时通讯(IM)系统理论架构方案
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)
本文将要分享的是如何从零实现一套基于Netty框架的分布式高可用IM系统,它将支持长连接网关管理、单聊、群聊、聊天记录查询、离线消息存储、消息推送、心跳、分布式唯一ID、红包、消息同步等功能,并且还支持集群部署。
JackJiang
2023/06/09
1.3K0
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)
SpringBoot集成开源IM框架MobileIMSDK,实现即时通讯IM聊天功能
MobileIMSDK  是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持UDP 、TCP 、WebSocket 三种协议,支持iOS、Android、H5、标准Java平台,服务端基于Netty编写。
JackJiang
2022/05/05
3.1K0
SpringBoot集成开源IM框架MobileIMSDK,实现即时通讯IM聊天功能
支持百万人超大群聊的Web端IM架构设计与实践
现在IM群聊产品多种多样,有国民级的微信、QQ,企业级的钉钉、飞书,还有许多公司内部的IM工具,这些都是以客户端为主要载体。而且群聊人数通常都是有限制,微信正常群人数上限是500,QQ2000人,收费能达到3000人,这里固然有产品考量,但技术成本、资源成本也是很大的因素。笔者的业务场景上正好需要一个迭代更新快、轻量级(不依赖客户端)、单群百万群成员的纯H5的IM产品。
JackJiang
2025/03/13
1290
支持百万人超大群聊的Web端IM架构设计与实践
为自己搭建一个分布式 IM(即时通讯) 系统
之前分享过一篇《设计一个百万级的消息推送系统》;虽然我在文中有贴一些伪代码,依然有些朋友希望能直接分享一些可以运行的源码;这么久了是时候把坑填上了。
java进阶架构师
2019/03/01
2.6K0
为自己搭建一个分布式 IM(即时通讯) 系统
如何设计一款高性能的即时聊天服务
本系列将带大家从零开始搭建一个轻量级的IM服务端,麻雀虽小,五脏俱全,我们搭建的IM服务端实现以下功能:
DeROy
2021/12/13
1.4K0
如何设计一款高性能的即时聊天服务
研究微信即时通讯的服务端、朋友圈、红包、推送等方案
推送:采用增量推送的方式,设置一个sequence,服务端一个客户端一个,每次同步时客户端将cur_seq发给服务端,获得增量数据同步到本地。每个seq都是long型占8byte,考虑到微信用户6亿,Qps达到千万级别,则每秒要处理100兆的IO,相对来说比较大,如何降低呢,微信有一个AllocSvr和StoreSvr两个服务,分别来处理分配和存储,设计一个max_Seq和步长,将一定数量的用户比如连续ID一万个,设计在同一个Section,加上一个max_Seq,步长设为10000,此时可以10^3个等级的数据量,相对AllocSvr处理就简单一些,所以任何一个简单的事情在海量数据下,都会变成一个复杂的问题。另外添加步长,就涉及Old AllocSvr和New AllocSvr,需要根据已知配置文件,有哪些服务器可以切换,考虑到容灾还要做备份服务器,因此做互为备份是服务器能力不浪费的优秀设计;路由的切换也是根据seq的方式,使用路由表来切换的。
Java帮帮
2018/03/15
1.5K0
教你微信IM即时消息系统的架构设计
用户收发消息的终端,内置的客户端程序和服务端进行网络通信,用来承载用户的互动请求和消息接收功能。
JavaEdge
2021/02/23
2.2K0
跟着源码学IM(十二):基于Netty打造一款高性能的IM即时通讯程序
关于Netty网络框架的内容,前面已经讲了两个章节,但总归来说难以真正掌握,毕竟只是对其中一个个组件进行讲解,很难让诸位将其串起来形成一条线,所以本章中则会结合实战案例,对Netty进行更深层次的学习与掌握,实战案例也并不难,一个非常朴素的IM聊天程序。
JackJiang
2023/11/30
1.1K0
跟着源码学IM(十二):基于Netty打造一款高性能的IM即时通讯程序
【OpenIM原创】AppServer、AppClient、Open-IM-Server以及Open-IM-SDK之间的关系
Open-IM是由前微信技术专家打造的开源的即时通讯组件。Open-IM包括IM服务端和客户端SDK,实现了高性能、轻量级、易扩展等重要特性。开发者通过集成Open-IM组件,并私有化部署服务端,可以将即时通讯、实时网络能力快速集成到自身应用中,并确保业务数据的安全性和私密性。
用户8964349
2021/09/23
2.1K0
【OpenIM原创】AppServer、AppClient、Open-IM-Server以及Open-IM-SDK之间的关系
单独对 websocket 抽象封装,支撑了公司不同业务的消息即时通讯!
公司之前很多涉及到后端需要主动与前端web交互的业务,代码耦合严重,新的业务场景需要即时通信的得重新接入websocket,花费很多时间和精力,因此需要将websocket(缩写为:ws)抽象为公司内部的通讯服务,可以解决业务不同需求,比如:
码猿技术专栏
2024/07/31
3411
单独对 websocket 抽象封装,支撑了公司不同业务的消息即时通讯!
通讯协议与即时通讯[通俗易懂]
客户端不断的查询服务器,检索新内容。这种方式的缺点十分明显,如果轮询频率过快,会大量消耗网络带宽和电池;
全栈程序员站长
2022/08/05
2.3K0
一套高可用、易伸缩、高并发的IM群聊架构方案设计实践
本文原题为“一套高可用群聊消息系统实现”,由作者“于雨氏”授权整理和发布,内容有些许改动,作者博客地址:alexstocks.github.io。应作者要求,如需转载,请联系作者获得授权。
JackJiang
2018/10/17
2.2K0
零基础IM开发入门(四):什么是IM系统的消息时序一致性?
本文引用了沈剑《如何保证IM实时消息的“时序性”与“一致性”?》一文的图片和内容(由于太懒,图没重新画),原文链接在文末。
JackJiang
2020/11/04
1.3K0
零基础IM开发入门(四):什么是IM系统的消息时序一致性?
即时通讯(IM)开源项目OpenIM本周版本发布-v1.0.6
OpenIM是由前微信技术专家打造的*开源*的即时通讯组件。OpenIM包括IM服务端和客户端SDK,实现了高性能、轻量级、易扩展等重要特性。开发者通过集成OpenIM组件,并私有化部署服务端,可以将即时通讯、实时网络能力快速集成到自身应用中,并确保业务数据的安全性和私密性。代码100%开源,开源协议Apache-2.0 License任何企业和个人都可以免费使用(包括商用)。开发者可以选择自行安装私有化部署,基于SDK二次开发。
用户8964349
2021/12/06
1.6K0
即时通讯(IM)开源项目OpenIM本周版本发布-v1.0.6
推荐阅读
相关推荐
通俗易懂 即时通讯初学者入门 WhatsApp技术架构
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验