上一章和大家分享了《http如何像tcp一样实时的收消息?》, 本章来聊一聊即时通讯(Instant Messaging,后简称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系统中消息投递的最核心技术。

五、可靠消息投递存在什么问题
期望六个报文完成消息的可靠投递,但实际情况,msg:N,ack:N这两个报文都可能丢失(原因如第二章所述,可能是服务器奔溃、网络抖动、或者客户端奔溃),此时client-A都收不到期待的ack:N报文,即client-A不能确认client-B是否收到“你好”,但这两个报文的丢失对应的业务影响又大有不同:

1)msg:N包丢失,业务结果是client-B没有收到消息

2)ack:N包丢失,业务结果是client-B收到了消息,只是client-A不知道而已

那怎么办呢?

六、消息的超时与重传
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收到重复的消息,那怎么办呢?

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

九、其他
1)上述设计理念,由客户端重传,可以保证服务端无状态性(架构设计基本准则)
2)如果client-B不在线,im-server保存了离线消息后,要伪造ack:N发送给client-A

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

3)im系统难以做到系统层面的不丢不重,只能做到业务层面的不丢不重

末了,微信的消息是不是这么发送的,偶不太清楚,清楚的同学可以说一说。

微信为什么不丢消息?相关推荐

  1. 微信为啥不丢“离线消息”?

    参考 需求缘起 当发送方用户A发送消息给接收方用户B时,如果用户B在线,之前的文章<微信为啥不丢"在线消息"?>聊过,可以通过应用层的确认,发送方的超时重传,接收方的去 ...

  2. 面试官问:Kafka 会不会丢消息?怎么处理的?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! Kafka存在丢消息的问题,消息丢失会发生在Broker, ...

  3. js版微信测试号推送消息、生日、纪念日、网易云热评、舔狗日记【JavaScript版】保姆级教程 青龙面板做微信测试号推送生日、纪念日

    文章目录 微信测试号推送消息 一.申请微信测试号 二.下载nodeJs 1.下载安装包 2.检查是否安装成功 三.设置测试号发送信息的模板 四.编写发送消息代码(必须装好nodeJs) 1.编写代码 ...

  4. 《近匠》融云,自主研发真正不丢消息的IM云服务

    摘要:<近匠>第90期,融云即时通讯云源自飞信团队,拥有8年IM技术积累,却推倒重来,从第零行开始写代码,自己做一套全新的通讯协议和服务端架构,不丢消息.快速迭代反馈,并将逐步落实SDK开 ...

  5. 刨根问底,Kafka消息中间件到底会不会丢消息

    大型互联网公司一般都会要求消息传递最大限度的不丢失,比如用户服务给代金券服务发送一个消息,如果消息丢失会造成用户未收到应得的代金券,最终用户会投诉. 为避免上面类似情况的发生,除了做好补偿措施,更应该 ...

  6. delphi 企业微信消息机器人_简单用VBS调用企业微信机器人发定时消息的方法

    去年在企业微信群当中突然看到多了一个叫多群机器人的东西: 企业微信群机器人 以为是升级了什么黑科技,看了下说明,原来目前功能是一个接收自定义消息的Webhook接口,可以通过调用接口把自定义消息推送到 ...

  7. 微信小程序模板消息(服务通知消息)原始post工具封装(不使用jar包--坑比较多),解决47001(JSON格式)和中文乱码问题

    微信小程序模板消息(服务通知消息)原始post工具封装(不使用jar包--坑比较多),解决47001(JSON格式)和中文乱码问题 参考文章: (1)微信小程序模板消息(服务通知消息)原始post工具 ...

  8. 微信服务通知消息找回_第三方平台微信服务号模板消息怎么发送

    使用公众号平台模板消息功能,无法发送模板消息,如果想要发送模板消息,可以用第三方平台微号帮功能模板消息群发实现,也可自己根据公众号平台的接口开发实现,均可以为微信服务号发送模板消息,且发送模板消息不占 ...

  9. kafka 重复消费和数据丢失_刨根问底,Kafka消息中间件到底会不会丢消息

    大型互联网公司一般都会要求消息传递最大限度的不丢失,比如用户服务给代金券服务发送一个消息,如果消息丢失会造成用户未收到应得的代金券,最终用户会投诉. 为避免上面类似情况的发生,除了做好补偿措施,更应该 ...

最新文章

  1. Python-day-9- RabbitMQ队列
  2. finally 90%
  3. 2020idea创建web项目_Spring Boot + Mybatis 多模块(module)项目的完整搭建教程
  4. java button 圆角_UIButton具有渐变边框和圆角
  5. 看我如何用Dataphin实现自动化建模
  6. 优化基于ExtJS 4.1的应用
  7. FileOutputStream 类 和 FileInputStream类的简单介绍,附代码演示。以及一个复制媒体文件的小程序。
  8. 由浅入深理解索引的实现(2)【转】
  9. 宽依赖和窄依赖_Kardemir开始生产窄钢板,进入板材市场
  10. mysql怎么实现的主从复制_【mysql】mysql实现主从复制
  11. 如何调用畅捷通接口_用友金蝶多组织多账套的不同数据如何合并?
  12. 数字电路逻辑关系式化简(代数运算)
  13. lbochs模拟器最新版_bochs模拟器官方下载
  14. Chui-Wen Chius Note: C++ 使用 JScript 和 VBScript
  15. 学习虚幻4(一)U3D与UE4的比较
  16. 伦敦 quant_伦敦统一用户组8
  17. 大学计算机科学与技术试题,大学计算机试题模拟卷3-大学教育计算机科学与技术类计算机及应用试卷与试题.pdf...
  18. 我做程序员的那些日子
  19. python教育数据挖掘_Python 数据分析 与 数据挖掘 (介绍篇)
  20. 什么是license

热门文章

  1. [洛谷1390]公约数的和
  2. Java算法-奇怪的分式
  3. java web中中文乱码问题汇总
  4. 五种网络管理技巧优化网络办公环境
  5. Spring框架IoC和传统bean调用的区别
  6. mysql查找执行效率慢的SQL语句
  7. 网络经典命令行【网络高手必备】
  8. 我在 SUN TECH DAY
  9. 高流量大并发Linux TCP性能调优
  10. Linux和unix中 awk 的print浅谈