`

IM如何保证消息可靠性

    博客分类:
  • IM
IM 
阅读更多
转自:https://blog.csdn.net/u014105540/article/details/80539507
今天手机的微信收到的消息总是会延迟,于是了解了一下。
消息的可靠性,即消息的不丢失和不重复,是im系统中的一个难点。当初qq在技术上(当时叫oicq)因为以下两点原因才打败了icq:
1)qq的消息投递可靠(消息不丢失,不重复)
2)qq的垃圾消息少(它antispam做得好,这也是一个难点,但不是本文重点讨论的内容)
今天,本文将用十分通俗的语言,来讲述IM系统中消息可靠性的问题。

一、报文类型
im的客户端与服务器通过发送报文(也就是请求包)来完成消息的传递,报文分为三种,请求报文(request,后简称为为R),应答报文(acknowledge,后简称为A),通知报文(notify,后简称为N),这三种报文的解释如下:
这里写图片描述
R:客户端主动发送给服务器的报文
A:服务器被动应答客户端的报文,一个A一定对应一个R
N:服务器主动发送给客户端的报文

二、普通消息投递流程
用户A给用户B发送一个“你好”,很容易想到,流程如下:
这里写图片描述
1)client-A向im-server发送一个消息请求包,即msg:R
2)im-server在成功处理后,回复client-A一个消息响应包,即msg:A
3)如果此时client-B在线,则im-server主动向client-B发送一个消息通知包,即msg:N(当然,如果client-B不在线,则消息会存储离线)

三、上述消息投递流程出现的问题
从流程图中容易看到,发送方client-A收到msg:A后,只能说明im-server成功接收到了消息,并不能说明client-B接收到了消息。在若干场景下,可能出现msg:N包丢失,且发送方client-A完全不知道,例如:
1)服务器崩溃,msg:N包未发出
2)网络抖动,msg:N包被网络设备丢弃
3)client-B崩溃,msg:N包未接收
结论是悲观的:接收方client-B是否有收到msg:N,发送方client-A完全不可控,那怎么办呢?

四、应用层确认+im消息可靠投递的六个报文
upd是一种不可靠的传输层协议,tcp是一种可靠的传输层协议,tcp是如何做到可靠的?答案是:超时、重传、确认。
要想实现应用层的消息可靠投递,必须加入应用层的确认机制,即:要想让发送方client-A确保接收方client-B收到了消息,必须让接收方client-B给一个消息的确认,这个应用层的确认的流程,与消息的发送流程类似:
这里写图片描述
4)client-B向im-server发送一个ack请求包,即ack:R
5)im-server在成功处理后,回复client-B一个ack响应包,即ack:A
6)则im-server主动向client-A发送一个ack通知包,即ack:N
至此,发送“你好”的client-A,在收到了ack:N报文后,才能确认client-B真正接收到了“你好”。
会发现,一条消息的发送,分别包含(上)(下)两个半场,即msg的R/A/N三个报文,ack的R/A/N三个报文,一个应用层即时通讯消息的可靠投递,共涉及6个报文,这就是im系统中消息投递的最核心技术(如果某个im系统不包含这6个报文,不要谈什么消息的可靠性)。

五、可靠消息投递存在什么问题
期望六个报文完成消息的可靠投递,但实际情况下:
1)msg:R,msg:A报文可能丢失,此时直接提示“发送失败”即可,问题不大
2)msg:N,ack:R,ack:A,ack:N这四个报文都可能丢失(原因如第二章所述,可能是服务器奔溃、网络抖动、或者客户端奔溃),此时client-A都收不到期待的ack:N报文,即client-A不能确认client-B是否收到“你好”,那怎么办呢?

六、消息的超时与重传
client-A发出了msg:R,收到了msg:A之后,在一个期待的时间内,如果没有收到ack:N,client-A会尝试将msg:R重发。可能client-A同时发出了很多消息,故client-A需要在本地维护一个等待ack队列,并配合timer超时机制,来记录哪些消息没有收到ack:N,以定时重发。
这里写图片描述
一旦收到了ack:N,说明client-B收到了“你好”消息,对应的消息将从“等待ack队列”中移除。

七、消息的重传存在什么问题
第五章提到过,msg:N报文,ack:N报文都有可能丢失:
1)msg:N报文丢失,说明client-B之前压根没有收到“你好”报文,超时与重传机制十分有效
2)ack:N报文丢失,说明client-B之前已经收到了“你好”报文(只是client-A不知道而已),超时与重传机制将导致client-B收到重复的消息,那怎么办呢?
启示:
平时使用qq,或许大伙都有类似的体验,弹出一个对话框“因为网络原因,消息发送失败,是否要重发”,此时,有可能是对方没有收到消息(发送方网络不好,msg:N丢失),也可能已经收到了消息(接收方网络不好,反复重传后,ack:N依然丢失),出现这个提示时,大伙不妨和对端确认一下,看是哪种情况。

八、消息的去重
解决方法也很简单,由发送方client-A生成一个消息去重的msgid,保存在“等待ack队列”里,同一条消息使用相同的msgid来重传,供client-B去重,而不影响用户体验。

九、其他
1)上述设计理念,由客户端重传,可以保证服务端无状态性(架构设计基本准则)
2)如果client-B不在线,im-server保存了离线消息后,要伪造ack:N发送给client-A
3)离线消息的拉取,为了保证消息的可靠性,也需要有ack机制,但由于拉取离线消息不存在N报文,故实际情况要简单的多,即先发送offline:R报文拉取消息,收到offline:A后,再发送offlineack:R删除离线消息

十、总结
1)im系统是通过超时、重传、确认、去重的机制来保证消息的可靠投递,不丢不重
2)切记,一个“你好”的发送,包含上半场msg:R/A/N与下半场ack:R/A/N的6个报文

个人消息是一个1对1的ack,群消息就没有这么简单了,群消息存在一个扩散系数,如果大家感兴趣,下一次将和大家讨论im群消息的可靠投递。
分享到:
评论

相关推荐

    J-IM即时通讯系统-其他

    J-IM 是用JAVA语言,基于t-io开发的轻量、高性能、单机支持几十万至百万在线用户IM,主要目标...7、内置消息持久化(离线、历史、漫游),保证消息可靠性,高性能存储8、各种丰富的API接口。9、零成本部署,一键启动。

    Java基于Netty实现的高性能分布式IM即时通信系统源码+项目说明.tar

    `RIM`是基于Netty实现的面相开发者的高性能分布式即时通信系统,保证消息的实时性、有序性、可靠性。 ## 技术栈 | 名称 | 作用 | | -------------- | ----------------------------------------------------------...

    高可用推送集群Quick-Know.zip

    QK是一个基于Golang开发的基于Mqtt协议的高可用推送集群。...保证用户在线可靠性完善的Restful API,为用户提供全面的对App操作先其仍然处于开发状态并且发布了第一个alpha版本。 标签:Quick

    netty-im-demo:基于netty的im系统

    Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说,Netty是一个基于NIO的客户、服务器端编程框架,使用Netty可以确保你快速和简单的开发出一...

    基于SSH+Redis+MySQL的IM即时聊天系统实现.zip

    自1998年首次发布以来,MySQL以其卓越的性能、可靠性和可扩展性,成为全球范围内Web应用程序、企业级解决方案以及其他各种数据处理场景的首选数据库平台之一。 以下是对MySQL数据库的详细介绍: 核心特性与优势 ...

    人工智能原理课程实验1,numpy实现Lenet5,im2col方法实现的.zip

    可靠性:相较于人类,人工智能可以更快速、更准确地执行任务,并且不会受到疲劳、情绪等因素的影响,提高了任务执行的可靠性。 个性化服务:通过分析大量的用户数据,人工智能可以为用户提供个性化的服务和推荐,...

    skycoll视频会议系统

    Skype还使用了端对端的加密技术,保证了通讯的安全可靠性。 Skype迄今已有28种语言的版本,注册用户已达3.7亿,遍布世界上几乎每一个国家。每天都会增加新的用户15.5万人,每时每刻都会有近2000万用户在享受...

    一种基于Java企业内部及时通讯软件设计.doc

    考虑到UDP协议不可靠性,该通信器的通信协议 中采用了确认与重传机制来保证数据传输的可靠性,采用了动态的超时重传定时器值提 高了本协议的适应性和灵活性,还使用了在应用层对数据进行分片的方法来避免IP层分 片的...

    Web请求异步处理降低依赖风险

    SA为了保险起见还是通过请求方式来做定时的心跳检测,保证服务集成平台的可靠性。结果旺旺推广开始的第一天,SA的报警短信就在几个忙时段不停的发告警,但是察看生产环境的服务器状况以及应用状况也看不出有什么问题...

    皮肤控件研究文档,破解后的库文件,皮肤设计工具使用教程

    同时也需要有一套机制来管理自绘部分的图片,颜色等资源,不然无法保证界面色调的一致性。 3.4 界面库高效性 界面库的效率是一个核心问题。糟糕的界面库效率会带来极坏的用户体验,这也应是公司在考虑一个界面控件...

    GG叮咚2011版本聊天软件

    在IM表现形式的基础上融和SNS、LBS等全新特性,同时继承互联网源本的“免费”、“开放”、“利他”基因,并以“清静心”、“平等心”、“慈悲心”、“无所得心”来作为自我约束准则的“可可豆”将会成为大家在网络上...

    防泄密、内网管理、上网行为管理-鸿智数据安全管理系统V8.0

    文件备份要保证机密文件的安全性,首先要保证机密文件的可用性。系统可以对机密文件进行多版本自动备份(最多可备份5个版本),提供本地备份和远程备份两种备份模式,提供密文备份和远程备份两种备份格式。让用户在...

    基于Java的即时通讯系统设计与实现【文献综述】.doc

    使用无联接方式时其系统开销比无联接方 式小,但通信链路提供了不可靠的数据报服务,不能保证信源所传输的数据一定能够到 达信宿,在该方式下,通信双方不必创建一个联接过程和建立一条通讯链路,网络通信 操作在...

    Intel®Matrix Storage Manager v11.6.0.1030等7个版本合集、IDE切换为AHCI的方法

    Intel Matrix Storage Manager 是提高计算机存储子系统的性能和可靠性的应用程序。要管理存储子系统,单击“开始”菜单并启动 Intel Matrix Storage Console。进入 Console(控制台)后,从“查看”菜单选择“基本...

    博客系统数据库设计.doc

    需求分析 2.1功能目标 1、规范完善的基础信息设置 2、操作简单,快捷方便 3、数据存储安全可靠 4、信息分类清晰准确 5、强大的查询功能,保证数据查询的准确 6、对用户输入的数据,系统进行严格的审核的数据检验,尽...

    Android高级编程--源代码

     《android高级编程》首先简要介绍android软件栈,接着陈述为手机创建稳定可靠、赏心悦目的应用程序的基本原理。通过学习,您可以打下牢固的理论根基,了解使用当前android 1.0 sdk编写定制移动程序所需的知识,还...

    博客系统数据库设计.pdf

    需求分析 2.1 功能目标 1、规范完善的基础信息设置 2、操作简单,快捷方便 3、数据存储安全可靠 4、信息分类清晰准确 5、强大的查询功能,保证数据查询的准确 6、对用户输入的数据,系统进行严格的审核的数据检验,...

    vc++ 应用源码包_1

    独立打包,保证可解压,内含大量源码,网上搜集而来。 Visual.C++编程技巧精选500例源代码 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、...

    vc++ 应用源码包_2

    独立打包,保证可解压,内含大量源码,网上搜集而来。 Visual.C++编程技巧精选500例源代码 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、...

Global site tag (gtag.js) - Google Analytics