即时消息的四大特征及实现方案

本文介绍了在即时通讯软件中如何保证消息的几个特性。

消息传输过程分为三个阶段:

其中,消息的上下行由C/S全双工通信保证,心跳保证通道的可用性。

消息处理由im-server实现,主要包括消息认证、消息审计和消息解包。它必须是稳定高效的,可以通过独立的服务来实现,以保证其可扩展性。

对于群组消息,需要解包,1个发送的包生成n个接收的包,其中n为当前群组成员数。

在用户1和用户2的单次聊天会话中,用户1发送了三条消息,分别是aa、bb和cc。

其中aa和cc发送成功,bb由于网络或设备问题,客户端自动重试3分钟后发送失败。是否重发会显示一个小按钮,用户可以决定是否重发。

如果用户点击按钮重新发送bb,那么user1和user2的消息列表将如何显示?

在用户1和用户2的单次聊天会话中,用户1发送了三条消息,分别是aa、bb和cc。

其中aa发送成功,bb和cc正在自动重传,user2发送dd和ee,user2发送成功。之后bb和cc自动转发成功。

那么,user1和user2的消息列表将如何显示呢?

在用户1、用户2和用户3的群聊会话中,用户1和用户2同时向im-server发送消息,甚至是im-server生成的时间戳。

那么,如何展示user1,user2,user3的消息列表呢?

消息的有序性更多的是一种用户体验。

如何实现消息的可靠性,保证消息不重不漏,需要从消息传输的三个环节入手。

在c->在S的过程中,采用send-ack,如果客户端没有收到send-ack,会自动重传。

这个过程可以保证消息不被泄露。但是,服务器收到的消息可能是重复的。如果存在具有重复sequenceId的消息,服务器必须复制它。

服务器处理消息的过程中可能会涉及到多个服务,比如SessionManager和Auditor。

为了保证消息的可靠性,与RabbitMQ的每一次交互都需要保证成功送达和安全消费。

在s->在C的处理过程中,采用了receive-ack的方法。如果服务器没有收到receive-ack,它将自动重新传输它。

这个过程可以保证消息不被泄露。但是,接收者收到的消息可能是重复的。如果存在具有重复sequenceId的消息,接收方必须复制它。

如果接收方不在线,当接收方在线时,可以通过API获取历史消息,并对历史消息列表进行两次检查(服务器端必须完成第一次检查),确保没有重复sequenceId的消息。

IM系统不标准。虽然XMPP协议试图解决这个问题,但事实证明这是不现实的。

几乎所有的IM厂商都有自己的专有协议和不同的实现逻辑,这也决定了即使是同一个技术问题,IM也很难有固定的实现套路和标准的解决方案。

但是,必须实现IM系统的几个硬指标。

在实现过程中,需要考虑性价比,是追求更高的系统并发还是更可靠的数据流;是追求更大的系统吞吐量还是更好的可扩展性和容灾能力。

最后推荐一个IM专栏:

/u/jackjiang