消息传输的高可靠性在即时通讯系统中是最为基础、也是最核心的部分之一,同时也是衡量通讯系统的质量的重要指标。本文主要描述常见通讯系统模型的实现原理,分析影响消息传输可靠性的常见问题,并介绍有度即时通服务体系是如何通过架构及技术细节实现高可靠的消息送达机制。
快递式系统模型是常见的即时通讯系统模型,主要结构如下图所示:
即时通讯系统如何保障消息高可靠性_第1张图片
该模型的消息发送过程不是一个完整事务,以下这些场景将出现丢消息的问题:
1、 ClientA将发消息送给Server,Server收到后回复ClientA发送成功,后续中转由Server保障,此时如果Server进程重启,内存中的消息没有存储,将出现消息丢失。
2、 ClientA将消息成功发送给Server,Server转发给ClientB,ClientB网络层收到后回复接收成功,但ClientB尚未将消息保存到数据库,此时ClientB进程关闭,也将出现消息丢失;
3、 ClientA将消息成功发送给Server,Server发现ClientB为离线,将消息发送给离线消息服务,离线消息服务回复接收成功,但离线消息未保存进磁盘前进程异常退出,也将出现丢失消息;
后面出现了一种改进模型,这种改进可以保障网络层不丢消息,但从整体系统架构来看依然有漏洞,网络程序设计架构大体如下:
即时通讯系统如何保障消息高可靠性_第2张图片
网络层(Net)收到请求,回复对方消息已收到,接下来将请求抛给Logic层,Logic层将消息保存到Store层并抛给UI层。
通过实践发现,Net回复对方消息已收到后,消息未保存进数据库之前程序退出,将出现消息丢失。
如果是离线消息服务,网络层收到很多离线消息抛给Logic层,Logic落地磁盘速度如果跟不上,Logic的队列中将堆积有消息,此时服务重启,Logic队列中未保存的离线消息都将丢失。
这种演进解决原来系统中的问题1,但问题2、3并没有解决,快递式即时通讯系统消息到达率难以有效保障,容易由中间环节、程序设计等导致消息丢失。
邮件服务是一种历史悠久的通讯系统,客户端发送邮件是一个完整的事务,只有消息落地后才返回成功,中间任何一个环节出现故障都回复失败,该模式能保障发消息不丢,如果再保障接收方能成功拉取到消息,将演进出一种更极致的消息高到达率解决方案,邮件服务模型如下:即时通讯系统如何保障消息高可靠性_第3张图片
有度即时通讯系统参考邮件服务模型,消息服务器漫游,将邮件轮询机制改造为新消息push通知,系统采用微服务模式设计,支持服务器集群式部署及扩展,多种措施并用,保障消息到达率。
系统设计即采用先进的数据存储技术在服务器端存储消息,只要服务器确认接收到消息,消息将一直保存在服务器,不会随用户读取而删除。在网络异常、客户端设备异常时,仍能通过二次请求获取到消息。
微服务架构将业务相对独立的拆分为多个服务,可以分机部署,这种模式能够有效的实现故障隔离,提升整体服务的可靠性和可用性。
每个会话参与者的消息数据是共享的,避免从发送者发送成功转换到接收方待收消息的故障问题,只要发送的消息成功(成功即入库),整个会话参与人一定能拉取该消息。
客户端发送消息时通过调用RESTFUL API接口。API接口保障回复成功时即入库。当客户端调用接口失败或超时会采用多次重试机制,发送失败的消息客户端也会给出明确的提示来告诉发送方。
服务器的消息存储机制经过多次演进,从最开始的MySQL存储演变到现在的Redis+Leveldb,其可靠性接受极致。客户端发送消息立即入库,入库操作包含写入内存数据表(双表缓冲)和pending日志(异常保障),内存数据表满时转换为只读并持久化,持久化也是使用高效的顺序存储方式(受益于LevelDB的实现机制),同时可以使用备份服务器实现数据主从同步,确保文件系统发生故障时容灾恢复能力。
客户端通过服务器通知事件拉取消息,获取消息时会自动补全完整的消息记录。在网络发生波动时,客户端会重新建立连接并立即拉取所有的未读会话。