可靠的推送IM消息
一、 报文类型:
1、请求报文(request,后简称为为R);
2、应答报文(acknowledge,后简称为A);
3、通知报文(notify,后简称为N)。
R:客户端主动发送给服务器的报文;
A:服务器被动应答客户端的报文,一个A一定对应一个R;
N:服务器主动发送给客户端的报文;
二、 在线消息的可靠性:
消息投递流程:
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-B崩溃,都会导致msg:N消息丢失,而Client-A以为client-B已经收到消息;
消息的可靠性投递:
要想实现应用层的消息可靠投递,必须加入应用层的确认机制,即:要想让发送方client-A确保接收方client-B收到了消息,必须让接收方client-B给一个消息的确认:
1、client-B向im-server发送一个ack请求包,即ack:R;
2、im-server在成功处理后,回复client-B一个ack响应包,即ack:A;
3、则im-server主动向client-A发送一个ack通知包,即ack:N;
一个应用层即时通讯消息的可靠投递,共涉及6个报文:即msg的R/A/N三个报文,ack的R/A/N三个报文。
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队列”中移除。
消息的去重:
如果client-A不能收到报文ack:N,即client-A不能确认client-B成功收到了消息,此时会触发消息的超时和重发,如果之前client-B收到消息,而ack:N没收到导致消息重发,那么client-B有可能会重复收到消息;
解决方法是client-A为每条消息生成一个唯一的msgid(可以采用UUID),这样即时client-B收到了重复的消息,通过msgid的判断,也不会影响用户的体验;
三、 离线消息的可靠性:
离线消息的发送流程:
1、Step 1:用户A发送一条消息给用户B;
2、Step 2:服务器查看用户B的状态,发现B的状态为“offline”(即B当前不在线);
3、Step 3:服务器将此条消息以离线消息的形式持久化存储到DB中(当然,具体的持久化方案可由您IM的具体技术实现为准);
4、Step 4:服务器返回用户A“发送成功”ACK确认包(注:对于消息发送方而言,消息一旦落地存储至DB就认为是发送成功了)。
离线消息的拉取流程:
一次性拉取所有好友发送给用户B的离线消息,到客户端本地再根据sender_uid进行计算;
用户B一次性拉取所有好友发给ta的离线消息,消息量很大时,一个请求包很大、速度慢,容易卡顿;我们可以分页拉取:根据业务需求,先拉取最新(或者最旧)的一页消息,再按需一页页拉取,这样便能很好地解决用户体验问题。
消息的可靠性:
上面的流程中,如果在第三步从离线表中删除了离线消息,在执行第四步时,如果出现网路抖动、服务器宕机,B客户端宕机,那么就会造成离线消息丢失。那如何保证离线消息的绝对可靠性、可达性?
如同在线消息的应用层ACK机制一样,离线消息拉时,不能够直接删除数据库中的离线消息,而必须等应用层的离线消息ACK(说明用户B真的收到离线消息了),才能删除数据库中的离线消息。
消息的去重:
如果用户B收到了离线消息,但是ACK消息丢掉了,下次登录时消息还是会再次推送的,那么就会造成消息重复接收;
解决办法与前面的在线消息一样,可以为每条消息生成一个唯一的消息ID(msgid),然后在应用层通过对msgid判断去重,从而对用户体验无影响;
可靠的推送IM消息的更多相关文章
- C#微信公众号开发系列教程五(接收事件推送与消息排重)
微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...
- APNS推送通知消息负载内容和本地格式字符串
来源:http://hi.baidu.com/tangly888/blog/item/62948520121870559358074f.html 翻译苹果文档 地址: 翻译:tangly http: ...
- 微信开发之获取openid及推送模板消息
有很多的朋友再问我怎么获取code,openid之类的问题,在这里我就给大家分享一下. 在做微信支付是需要获取openid的,推送模板消息也是需要openid包括其他一些功能分享等也都是需要的,ope ...
- C#微信接口之推送模板消息功能示例
本文实例讲述了C#微信接口之推送模板消息功能.分享给大家供大家参考,具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2 ...
- FineReport如何手动推送APP消息
在报表填报成功后,发送消息至APP会提示数据已更新.再次期间用户需要有查看该模板的权限,如果没有的话,则无法接受到提示信息.那么在FineReport移动端中,如何手动推送APP消息呢? 具体用法 在 ...
- .net平台推送ios消息
1,ios应用程序中允许向客户推送消息 2,需要有苹果的证书以及密码(怎么获取,网上搜一下,需要交费的) 3,iphone手机一部,安装了该ios应用程序 4,.net 项目中引用PushSharp. ...
- 转:C#微信公众号开发之接收事件推送与消息排重的方法
本文实例讲述了C#微信公众号开发之接收事件推送与消息排重的方法.分享给大家供大家参考.具体分析如下: 微信服务器在5秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次.这样的话,问题就来了.有这 ...
- 微信公众号实现无限制推送模板消息!可向指定openID群发
微信认证的服务号才有推送模板消息接口所以本文需要在认证服务号的情况下学习 以上就是模板消息,只有文字和跳转链接,没有封面图.在服务号的后台添加功能插件-模板消息即可. 模板消息,都是在后台选择一个群发 ...
- phonegap 使用极光推送实现消息推送
最近一直在研究各种推送,ios的由于是apns,比较容易实现,但是andriod的就比较麻烦.后来看了很多解决方案,gcm明显是不行的,其他的方案更是一头雾水,而且需要做第二次开发,太麻烦,后来就选择 ...
随机推荐
- ccf数字排序
问题描述 给定n个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出. 输入格式 输入的第一行包含一个整数n,表示给定数字的个数. 第二行包含n个整数,相邻的整数之间用一个空格分隔,表示所 ...
- JAVA System.arraycopy 和Arrays.copyof 效率比较
System.arraycopy()源码.可以看到是native方法: native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中. ...
- Queue 实现生产者消费者模型
Python中,队列是线程间最常用的交换数据的形式. Python Queue模块有三种队列及构造函数: 1.Python Queue模块的FIFO队列先进先出. class Queue.Queue( ...
- XML文档的读、写
代码: XmlDocument doc = new XmlDocument(); doc.Load("Books.xml"); //1.加载要读取的XML文件 //要想看到数据得先 ...
- Error Code: 1175. You are using safe update mode and you tried to ......
MySQL提示的错误信息: Error Code: 1175. You are using safe update mode and you tried to update a table witho ...
- spring--boot @Valid的使用
spring--boot @Valid的使用 每天一个小知识点,每天进步一点点,总结是积累. springBoot @Valid的使用,解释一下.就是给摸个bean类属性(数据库字段)加一个门槛,比如 ...
- Harbor和YUM部署for CentOS 7
Harbor部署for CentOS 7 下载 wget https://storage.googleapis.com/harbor-releases/release-1.7.0/harbor-off ...
- shiro学习笔记-Subject#login(token)实现过程
本博文所有的代码均为shiro官网(http://shiro.apache.org/)中shiro 1.3.2版本中的源码. 追踪Subject的login(AuthenticationToken t ...
- list<map>排序
@Test public void test_when_test1() throws Exception { String[] strs = {"e", "ee" ...
- Android输入法框架系统(下)
程序焦点获取事件导致输入法显示 从上面可以知道程序获得焦点时,程序端会先间接的调用IMMS的startInput将焦点View绑定到输入法,然后会调用IMMS的windowGainFocus函数,这个 ...