《即时消息技术剖析与实战》学习笔记2——支持用户点对点聊天的消息收发架构

大部分消息进行服务端存储,是为了便于查看历史消息或者用于暂存离线消息。
一个支持用户点对点聊天的消息收发架构主要包括三部分:消息存储、消息未读和消息收发通道。

一、消息存储

假设收发双方的历史消息都是相互独立的,即一方发送消息后删除了消息,另一方仍可获取到这条消息,则消息的存储需要用到两张表:消息内容表(图中的 user_message 表)和消息索引表(图中的 user_message_history 表)。前者主要存储消息ID、消息内容、消息类型、消息创建时间等,后者可以理解为历史聊天记录,记录了收发双方的用户ID,通过消息ID和前者关联。
一般 IM 系统还需要一个最近联系人列表(图中的 user_message_contacter 表),使互动双方能快速查找需要聊天的对象,联系人列表还会携带两人最近一条聊天消息用于展示,该表与消息索引表的区别在于:消息索引表存储收发双方的历史消息记录,联系人表主要用于查询某个用户最近的所有联系人。

假设张三给李四发送了一条消息,会先向消息内容表插入一条数据(假设是图中 user_message 表 ID 为 1001 的记录),然后向消息索引表插入两条数据,一条是用户ID为张三的记录(假设是图中 user_message_history 表 ID 为 30923 的记录),一条是用户ID为李四的记录(假设是图中 user_message_history 表 ID 为 30922 的记录),两条记录的消息ID都是 1001。
同时会分别更新张三的最近联系人和李四的最近联系人,前者是查找联系人表中是否有用户ID为张三USERID且互动人ID为李四USERID的记录,如果没有,则插入一条新的联系人记录,最新消息ID就是 1001;反之,如果张三和李四之前已经有过聊天记录,就更新最新消息ID即可。同样的办法更新李四的最近联系人。

如果想列出张三与李四的对话消息记录,可以使用如下 SQL 语句查询:

select * from user_message_history where user_id = 张三USERID or contacter_id = 张三USERID;

二、消息未读

如果一方发送消息,而接收方不在线或限制通知栏提醒权限,则需要有未读提醒来作为补救措施。具体实现是设置一个未读消息总数和针对某个接收方会话的消息未读数。
当张三给李四发送消息,IM 服务端接收到消息后,给李四的总未读数加 1,给李四和张三的会话未读数加 1;
李四查看这条消息后会执行未读数变更,将李四的总未读数减 1,将李四和张三的会话未读数减 1。
一般,需要支持“消息多终端漫游”的功能,未读数存储在 IM 服务端,反之选择本地存储即可。

三、消息收发通道

  • 发送通道

客户端 和 IM 服务端之间维持一个 TCP 长连接,IM 服务端提供发送消息的 API;
当客户端有消息发送时,会以私有协议封装这条消息,然后调用 API 把消息发给 IM 服务端。

  • 接收通道

IM 服务端的网关服务和接收消息的客户端之间维持一个长连接(TCP长连接 或 Websocket长连接),借助 TCP 能同时接收与发送数据的能力,把消息从 IM 服务端推送给接收方。若接收方不在线(无网络或未打开APP),可借助第三方操作系统系别的辅助通道、各种设备的厂商通道,将消息通过通知栏的方式推送给接收方。

猜你喜欢

转载自www.cnblogs.com/sunshineliulu/p/11441026.html