跳到主要内容

IM 系统

IM 即时通讯的英文全称是 Instant messaging,也就是即时聊天系统,比如微信、QQ、钉钉等,也可以用于客服、私信等场景。

这里我们用一个基础的 IM 系统来展示清林云自定义应用能力。基础版本能满足大部分基础需求,但是每家组织的 IM 系统需求都不相同,所以你也可以在这个基础上再自行添加更多高级的个性化功能。

需求#

清林云控制台需要一个 IM 系统,能够实现组织成员之间的即时聊天功能。

首先需要“群聊、单聊”功能,毕竟组织内和分组内都需要多人聊天和直接沟通。

然后所有消息需要支持多端同步,并且能永久保存,很多有价值的消息都是组织资产。

最后虽然清林云的系统不需要好友关系,但是 IM 一般都需要这个,所以也要加上,为其他使用该应用的客户提供方便。

功能分析#

首先我们需要群聊和单聊,虽然它们不一样,但本质都是差不多的,这里我们把单聊设置为特殊的群聊就两者同时实现了,而且功能更多,可随时升级为多人聊天(视产品需求)。而且该方法极大地减少了开发者的心智和开发量。前端只需要稍微做个判断显示不同样式就可以同时实现两种聊天。

IM 的系统模型和 Feed 流系统很像,也分为那三类:

一、多写模型#

这是微信采用的模式,当一个用户在群里发送消息后,后端将先查询所有群成员,然后将该消息的数据插入到所有群成员的消息序列中。

比如说,当微信群有 200 个成员时,每当你发一条消息,微信后端将会先查询所有群成员,然后分别给这 200 人的消息队列中插入你发送的信息。

该模型的优势是逻辑简单,用户刷新消息列表时性能好,占用查询资源小。

但缺点是发布时不好瞬间写入太多数据,比如当群有一万个成员时,那么发一条消息将会在后端瞬间写一万条数据,这就给后端的压力太大,很难实现。这也是为什么微信只允许一个群最多只能有 500 个成员的原因之一。

另外该模型需要将消息存在客户端本地,难以同步和保存群消息。

二、多读模型#

上面的情况当然不能适用于有超大群的产品,所以就要使用拉模型。

当用户打开产品时,将会先查询用户的会话列表和对应的群,然后根据群的消息序列减去用户会话的消息序列计算出未读数,并根据最新消息时间排序。

使用该模型时,比如有一个大群有 10 万成员,当某人发送一条消息时,仅仅是一个简单的新增一条数据。而当其他用户打开产品或者是刷新会话时,才会查询到该内容并得到未读提示,同时在线并刷新的群成员当然不会太多,所以就实现了大量群成员情况下的 IM 系统。

该模型的缺点就是略微复杂,然后用户查询的资源消耗多,这也就是为什么该类产品限制最多只能加几百个群的原因之一。

三、读写结合模型#

上面两种方法都有优点和缺点,所以就又出现了读写结合模型。也是钉钉采用的方式,所以它才能支持万人群。

当一个群内成员数小于 500(假设值)时,发送消息时将使用多写模型,超过时使用多读模型。

当用户打开产品后,查询会话列表中的大群,读取群信息计算未读数和最新消息,而那些小群的内容则从消息序列中读取出来合并计算。

该模型的缺点就是实现起来较为复杂。

本应用#

清林云以前实现过很多类似系统,所以就直接简化了很多复杂的部分,然后这里我们将实现一个非常简洁的多读模型,适用于轻量级、企业级、在线化的 IM 场景。

毕竟大部分产品不是微信和钉钉,能够随意让用户下载 APP 将消息存在客户端本地。我们更需要支持大群,消息保存在云端能够轻易多端同步这些功能。

IM 系统之所以复杂就是因为会话列表的动态功能,需要时刻计算并提醒最新消息,未读数等。我们使用了一个巧妙的逻辑,当群成员发送一条小时时,会同时将该消息的内容、发送者名称和消息序列号更新到群信息上,然后其他用户刷新会话列表时,先查询该用户的所有会话及相对应的群信息,会话保存了上次点击时的消息序列号,这样,最新的群信息中的消息序列号减去会话的序列号就是未读数。当用户进入群聊后再退出到会话时则更新会话的序列号为最新消息的序列号。

这样只需要按照会话对应的群最新消息时间排序即可。

该方法不能使用户有太多的会话比如 1000 个以上,不然查询较慢,但是该模型支持超大群,开发简单,非常适用于现代化的 IM 系统。

数据库结构#

Group 群#

群是一切通信的基础,可以是多人大群,也可以是单聊群。把单聊也做成以群为基础会减少很多开发量,只需要前端判断一下并稍微修改样式即可。

Group

GroupUser 群成员#

采用 C2 引擎,就可以同时查询群成员和用户的所有群。

GroupUser

Chat 会话#

会话主要用于聊天列表,可以查看最近的群消息,通过会话查询群信息,可以通过群的消息序列减去会话的消息序列得出未读消息数。

更新会话的消息序列同步为群的消息序列就代表已读。

IM 应用的首页就是查询用户的所有会话和群信息,然后根据最新消息时间排序,计算未读数,显示群名、最新消息内容和发送者昵称。

Chat

Message 消息#

消息都归属于某个群,简单的可以使用 content,复杂的内容显示就需要 type 和 body 共同配合,实现语音消息、图片消息、视频、引用、富文本等等。

Message

Timeline 序列#

用于推模式,发消息时查询所有群成员然后推送到他们的序列中,然后其他用户上线后从自己的序列中拉取消息到本地数据库。

Timeline

Profile 资料#

用户资料,用户社交应用,可以替换用户系统的资料,也可以在这里设置个性化资料,以及加好友方式等,其中 某某号 类似于微信号,可以通过它查询到用户资料。

Profile

Friend 好友#

好友关系,注意双方都需要创建,因为各自的备注、资料等都不相同。删除时可以学微信只删除单方,双方同时删除则需要两个数据都删除。

Friend

Apply 好友申请#

用于有好友关系的应用去做好友验证。

Apply

API#

createGroup#

创建群,同时会创建用户的群成员,消息,和会话。

createGroup

createGroup2

createGroup3

updateGroup#

修改群信息,需要群主才能更改。

updateGroup

deleteGroup#

删除群,需要群主才能删除,同时会删除所有群成员。

deleteGroup

getGroup#

查询群信息。

getGroup

createGroupUser#

添加群成员。

createGroupUser

updateGroupUser#

修改群成员资料。

updateGroupUser

deleteGroupUser#

删除群成员。

deleteGroupUser

getGroupUser#

查询群成员资料。

getGroupUser

getManyGroupUser#

查询群内所有成员。

getManyGroupUser

getManyUserGroup#

查询用户的所有群。

getManyUserGroup

createChat#

创建会话。

createChat

updateChat#

更新会话。

updateChat

deleteChat#

删除会话,该方法不会退出群,可以在群列表再次创建。

deleteChat

getManyChat#

查询所有会话和群信息,是最主要的一个 API。

getManyChat

createMessage#

新建消息并更新群信息。

createMessage

updateMessage#

编辑消息。

updateMessage

deleteMessage#

删除消息,只有群管理和本人可操作。

deleteMessage

getManyMessage#

获取群消息。

getManyMessage

createTimeline#

插入用户消息序列。

createTimeline

updateTimeline#

更新消息序列信息。

updateTimeline

deleteTimeline#

从消息序列中移除。

deleteTimeline

getManyTimeline#

获取用户的消息序列。

getManyTimeline

updateProfile#

更新用户资料,无则创建。

updateProfile

getProfile#

查询用户资料。

getProfile

getProfileByCid#

通过某某号查询用户资料,如需号唯一请搭配唯一性检查应用。

getProfileByCid

createApply#

创建好友申请。

createApply

updateApply#

更新好友申请。

updateApply

deleteApply#

删除好友申请。

deleteApply

getManyApply#

查询好友申请。

getManyApply

createFriend#

添加好友,会同时为对方也新建好友关系。

createFriend

updateFriend#

修改好友信息。

updateFriend

deleteFriend#

删除好友,会同时删除对方好友。

deleteFriend

getFriend#

查询好友资料。

getFriend

getManyFriend#

查询用户好友。

getManyFriend

界面#

暂无开源前端界面,后续清林云控制台将加入组织 IM,将使用该应用,并一同开源,敬请期待。