开源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