关于开源:开源IM项目OpenIM-客户端SDK架构剖析确保消息的有序性以及消息百分百可达

42次阅读

共计 2431 个字符,预计需要花费 7 分钟才能阅读完成。

开源 IM 我的项目 OpenIM 第二版对于客户端架构进行了部分重构,解决了音讯触发时序等 bug,也梳理了外部模块。目前曾经靠近序幕,本文重点解说 SDK 架构,以便大家深刻理解 OpenIM,并心愿大家能深度参加开发。很多开发者有个误区,认为 IM 的挑战次要在服务端,当然服务端有其挑战,包含性能、压力、时延等,但优良的 IM 架构须要服务端和客户端完满配合,比方音讯对齐机制,本地缓存和后盾数据同步,app 多端如何实时同步。

github 6.5K star 具体地址:

OpenIM Corporation
​github.com/OpenIMSDK
客户端重点问题总结:

(1)如何确保音讯有序性;

(2)如何确保音讯百分百可达;

(2)如果确保本地 db 和服务端数据的一致性;

(3)如何高效地实现多端同步;

(4)如果确保音讯即时达到;

(5)音讯发送的异步性,如何确保音讯发送的一致性;

本文从架构角度重点解答第 1,2 两个问题

客户端模块划分和协程模型

WsConn:ws 连贯管理器。提供函数供其余方调用,具体包含:

(1)ws 连贯服务端,和 OpenIM 服务端放弃长连贯;

(2)敞开 ws 连贯;

(3)通过 ws 发送申请;

WsRespAsyn:ws 申请 - 响应同步器,因为 ws 是异步解决,须要把申请和响应关联起来,提供函数供其余方调用(音讯发送,心跳发送,拉取历史音讯等)

(1)getCh:为每个申请生成一个 channel 和 msgIncr,应用 map 关联起来 msgIncr->channel

(2)notifyResp:对于 ws 收到的每个响应,通过 msgIncr 找到 channel,并往 channel 发送响应,告诉响应达到;

Ws:模块对 WsConn 和 WsRespAsyn 性能进行整合(1)申请响应同步化,提供函数 SendReqWaitResp,调用者通过 ws 发送申请后,期待此申请的响应达到。(2)对于接管到的推送音讯,把音讯写入 PushMsgAndMaxSeqCh channel,触发 MsgSync 音讯同步协程。

具体实现:ReadData 协程:接管服务端 ws 数据,并依据收到的数据类型(心跳、推送、踢出登录、拉取历史音讯等),触发不同的逻辑解决,(1)对于被动发送申请的响应,则调用 WsRespAsyn 的 notifyResp 响应触发接口;(2)对于 push 音讯,写入 PushMsgAndMaxSeqCh,触发 MsgSync 音讯同步协程。

MsgSync:音讯同步器;蕴含 Ws 和 conversationCh、PushMsgAndMaxSeqCh,启动音讯同步协程,对 PushMsgAndMaxSeqCh 中的读取的数据做解决,具体包含:

(1)从 PushMsgAndMaxSeqCh 读取服务端最大 seq:SvrMaxSeq(由 heartbeat 写入的),比照本地最大 seq:LocalMaxSeq 和服务端最大 seq: SvrMaxSeq,计算出缺失的 seq,从服务器拉取历史音讯,放入 conversationCh,触发 conversation 协程解决;

(2)从 PushMsgAndMaxSeqCh 读取 ws 推送音讯(由 Ws 的 ReadData 写入的推送音讯),如果音讯中的 seq+1==LocalMaxSeq,则写入 conversationCh,触发 conversation 解决,否则从服务端拉取音讯补齐 [LocalMaxSeq+1, seq],放入 conversationCh,触发 conversation 协程解决;

heartbeat:心跳管理器,包含 MsgSync

(1)心跳协程,从服务端定时获取最大 seq:SvrMaxSeq,而后把 SvrMaxSeq 让入 PushMsgAndMaxSeqCh,触发 MsgSync 音讯同步协程。

心跳和音讯同步交融

在心跳逻辑中触发音讯同步

(1)心跳协程每 30 秒通过 ws 从服务端获取最大 seq:SvrMaxSeq;

(2)心跳协程把 SvrMaxSeq 写入 PushMsgAndMaxSeqCh,触发 MsgSync 音讯同步协程;

(3)MsgSync 音讯同步协程从 PushMsgAndMaxSeqCh 中读取 SvrMaxSeq,

(4)MsgSync 音讯同步协程比照本地最大 seq: LocalMaxSeq 和 SvrMaxSeq,如果有缺失,则通过 ws 拉取历史音讯,范畴为:[localMaxSeq+1,SvrMaxSeq],

(6)MsgSync 音讯同步协程把拉取到的缺失的历史音讯写入 conversationCh 中;

(7)msg-conversation 音讯会话协程从 conversationCh 中读取缺失的历史音讯,依照音讯类型做业务解决,具体包含音讯落地本地 db,触发新音讯回调,触发会话扭转回调(或新增回调)

push 音讯触发同步

以 push 音讯触发同步:

(1)Ws 的 ReadData 协程收到服务端的推送音讯,

(2)Ws 的 ReadData 协程把推送音讯写入 PushMsgAndMaxSeqCh,触发 MsgSync 音讯同步协程。

(3)MsgSync 音讯同步协程从 PushMsgAndMaxSeqCh 中读取推送音讯,如果 msg 中的 seq 比本地最大 seq 大 1,则跳过第 4 步,间接写入 conversationCh,触发 conversation 解决;

(4)服务端拉取音讯补齐 [LocalMaxSeq+1, seq],放入 conversationCh,触发 conversation 协程解决;

(5)以下根本与以心跳触发同步过程一样。

总结

因为 seq 是依照音讯的主观事件递增生成的,对于推送音讯,如果比本地最大 seq 大 1,则音讯能够无缝对接。否则要么推送的是过期音讯,要么推送音讯和本地音讯有差别,须要通过 ws 拉取后写入本地,并触发相应回调。至此,客户端音讯和服务端音讯齐全同步,并保障新音讯回调的有序性。

重点参考咱们开发文档:https://doc.rentsoft.cn/

github 地址:OpenIM Corporation

正文完
 0