可靠的推送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明显是不行的,其他的方案更是一头雾水,而且需要做第二次开发,太麻烦,后来就选择 ...
随机推荐
- ASP.NET的内置对象 —— Response 对象
在 ASP.NET 中,页面实际上是一个输出 HTML 的可执行对象. 传统的 ASP 程序通常将 ASP 代码和 HTML 标签集成在一个文件中,或者将其分离于多个文 件. 当执行文件时,服务器回从 ...
- 【CSS】清除浮动的五种方式
清除浮动是一件功德无量的事情23333 这里记录一下清除浮动的多种方式 *首先要明确的是,为什么要清除浮动? A 影响其他元素定位 父盒子高度为0,子盒子全部浮动.定位,子盒子不会撑开父盒子,下面的元 ...
- C#winform窗体如何通过windowApi的FindWindow函数获取窗体句柄
在同一个程序里,传统方式是通过this来设置当前窗体的最大化.最小化等操作, 那么怎样通过窗体句柄来设置窗体的最大化.最小化呢? 1.界面布局 通过this设置窗体最大化: name:btnWindo ...
- 小程序animation动画效果(小程序组件案例)
WXML <view class="container"> <view class="page-body"> <view clas ...
- IScroll的诞生和缺点
转自http://lhdst-163-com.iteye.com/blog/1239784 iscroll.js是Matteo Spinelli开发的一个js文件,使用原生js编写,不依赖与任何js框 ...
- php通过$_SERVER['HTTP_USER_AGENT']获取浏览器useAgent
php通过$_SERVER['HTTP_USER_AGENT']获取浏览器useAgent
- [转载]三款SDR平台对比:HackRF,bladeRF和USRP
这篇文章是 Taylor Killian 13年8月发表在自己的博客上的.他对比了三款平价的SDR平台,认为这三款产品将是未来一年中最受欢迎的SDR平台.我觉得这篇文章很有参考价值,简单翻译一份转过来 ...
- 第七届蓝桥杯个人赛省赛--C语言B组
题目一 煤球数目 有一堆煤球,堆成三角棱锥形.具体:第一层放1个,第二层3个(排列成三角形),第三层6个(排列成三角形),第四层10个(排列成三角形),....如果一共有100层,共有多少个煤球? 请 ...
- Foundation--NSString , array and Dictionary
一,NSString的创建 NSString*str=@" a string ";//直接创建一个字符串常量,这样创建出来的字符串不需要释放内存 NSLog(@"%@&q ...
- matlab fgetl()
% % file=dir('/home/wang/Desktop/trainset/others/'); % % :length(file) % % path= strcat('/home/wang/ ...