▶ 1)实时性:
对于IM系统,“实时”二字是精髓,也是这项技术存在关键意义所在。它保证的是消息的实时触达。
举个例子:如果跟你的好友微信或qq聊天,我发的消息他不能即时收到,或者他发的信息你也不知道什么时候能收到,这基本上也就没法聊下去了(干吗不痛快打个电话呢)。
▶ 2)可靠性:
保证消息的不丢失和不重复,是IM系统的另一个关键技术特点。试想,当你在用qq或微信跟女朋友聊天,好不容易鼓起勇气向“她”表白,结果这消息要是丢包了,那肯定得卸载应用了,搞不好砸手机都有可能。当然,好话不说二遍,消息重复也同样恼人。
以下文章对消息的不丢/不重问题进行了深入探讨,有兴趣可以详读:
《IM消息送达保证机制实现(一):保证在线实时消息的可靠投递》
《IM消息送达保证机制实现(二):保证离线消息的可靠投递》
《IM群聊消息如此复杂,如何保证不丢不重?》
▶ 3)一致性:
对于单聊消息而言,保证同一个设备的时间顺序、不同设备的漫游同步,也是相当重要的一环。
IM系统中的消息交互,就到底就是人跟人在“说话”,前言不搭理后言、或者胡言乱语式的消息展现,那不是人疯了就是程序疯了,总之就是没法再聊下去了。
以下文章对消息时序问题进行了深入探讨,有兴趣可以详读:
《如何保证IM实时消息的“时序性”与“一致性”?》
《一个低成本确保IM消息时序的方法探讨》
▶ 4)安全性:
保证数据传输安全、数据存储安全、消息内容安全,也是IM系统必不可少的特性。尤其在私聊场景下,如果不能做到安全性,聊天的体验跟被人偷窥的感觉是没有区别的。
以下文章对IM的安全问题进行了深入探讨,有兴趣可以详读:
《即时通讯安全篇(二):探讨组合加密算法在IM中的应用》
《即时通讯安全篇(七):用JWT技术解决IM系统socket长连接的身份认证痛点》
《通俗易懂:一篇掌握即时通讯的消息传输安全原理》
7、IM的功能组成浅显的角度讲,一个典型的IM功能组成,无非就是以下5样:
1)联系人列表;
2)聊天界面;
3)消息发送通道;
4)消息接收通道;
5)消息存储;
6)消息未读数。
我们一样一样来说说各自的用途。
▶ 1)联系人列表:
这个很好理解,使用IM系统的第一步,就是要解决“跟谁聊”的问题。从功能表象上来说,联系人列表也就是社交关系列表,无非就是个信息列表界面,有什么特殊的地方?
联系人列表看似简单,实际上它是一系列IM系统的社交关系确立动作的结果体现。
要想建立联系人列表,你可能需要实现以下逻辑:
1)怎么能找到想要聊天的人?(需要实现随机查找?精确查找?)
2)怎么决定要不要跟这个人聊?(需要实现对方的个人信息查看)
3)开始发出好友请求;
4)被请求的一方,还可以决定是“同意”还是“拒绝”(“同意”该怎么处理?“拒绝”又该怎么处理?)。
总的来说,联系人列表的建立,是一个IM系统聊天关系确立的表现,不可或缺。
▶ 2)聊天界面:
聊天界面看似很平常,实际它就是IM系统客户端的核心功能所在,所有主要的IM功能都是通过它展现。
它应该具备的能力有:
1)各种聊天功能按钮:语音留言、图片、文字、表情、文件、实时电话、实时视频等;
2)各种聊天消息显示:各种消息都有不同的UI显示元素和处理逻辑;
3)流畅的使用体验:大量不同类型的消息显示时,不能卡顿;
4)即时显示聊天消息:网络线程收到的消息,要马上在UI上显示出来;
5)历史消息的加载:上次聊过的内容也得显示出来吧。
以上只是简单罗列,这看似简单的聊天界面,能把上面列表的事情做好,工作量也不小吧。
▶ 3)消息发送通道:
下图是一个典型的IM消息收发通道示意:
如上图所示,消息发送通道这个比较好懂,最浅显易懂的理解就是用tcp或udp,建立socket长连接,需要发消息的时候,wirte一下就过去了,好简单!
但,事情往往不是想象的这么简单:
1)如何保证这条socket长连接时一直处于可用的状态?
2)当socket长连接不可用时,用户此时发送的消息该怎么处理?
3)怎么保证发送的消息不丢?
4)怎么保证发送的消息不复重?
5)怎么保证发送的消息乱序?
6)当对方不在线时,发送的消息去哪了?
7)发送的消息,能保证实时送到?
这么一说,事情还挺多(那不废话吗。。。)。
▶ 4)消息接收通道:
正如上节中的消息收发通道示意图所示,消息接收通道也很好理解,对方通过消息发送通道write的消息,我得收到并显示啊。
要实现一个可靠的消息接收通道,也并非易事:
1)如何保证socket长连接通道能随时处于良好的边接状态(随时接收对方write的消息);
2)当socket长连接断开时,对方发送消息该怎么实现?
3)当socket恢复连接时,怎么恢复之前的聊天现场?
4)当我收到对方的消息时,对方怎么知道我已经收到了?
5)当重复收到对方的消息时,该怎么处理?
6)当收到的消息时序有错乱,该怎么处理?
▶ 5)消息存储:
消息存储这个功能好理解,聊天的消息如果存储,下次再聊的时候就不知道之前聊过什么,做不到这一点,这个IM系统的聊天体验好不起来。
那么,哪些情况下需要进行消息存储呢:
1)对方不在线时:聊天消息应该存储(这叫离线消息存储);
2)对方在线时:聊天消息也要存到本地存储(这叫消息缓存);
3)对方在线或不在线时:聊天消息都要存到服务端(用于实现多设备的消息漫游和同步)。
具体要存储的内容和时机也就上面这几样。
但技术落到实处,要做的事情同样少不了:
1)离线消息该怎么多久?
2)图片、短视频、大文件这类的离线消息,多媒体文件该怎么存(有可能量会很大)?
3)当本地的消息积累太多时,怎么能保证本地存储的性能?
4)当应用更新、升级或异常时,怎么能保证本地存储的完整性(不被破坏)?
5)怎么能保证多设备消息能不丢、不重、不乱?
这么多需要考虑的内容,也挺让人抓狂。
下图是一个IM系统的典型存储架构设计,了解一下: