从客户端的角度来看移动端IM即时通讯的消息可靠性和送达机制
如何确保IM 不丢消息是个相对复杂的话题,从客户端发送数据到服务器,再从服务器抵达目标客户端,最终在 UI 成功展示,其间涉及的环节很多,这里只取其中一环「接收端如何确保消息不丢失」来探讨,粗略聊下我接触过的两种设计思路。

说到可靠抵达,第一反应会联想到TCP 的 reliability。数据可靠抵达是个通用性的问题,无论是网络二进制流数据,还是上层的业务数据,都有可靠性保障问题,TCP 作为网络基础设施协议,其可靠性设计的可靠性是毋庸置疑的,我们就从 TCP 的可靠性说起。
在TCP 这一层,所有 Sender 发送的数据,每一个 byte 都有标号(Sequence Number),每个 byte 在抵达接收端之后都会被接收端返回一个确认信息(Ack Number), 二者关系为 Ack = Seq + 1。简单来说,如果 Sender 发送一个 Seq = 1,长度为 100 bytes 的包,那么 receiver 会返回一个 Ack = 101 的包,如果 Sender 收到了这个Ack 包,说明数据确实被 Receiver 收到了,否则 Sender 会采取某种策略重发上面的包。
数据可靠抵达网络层之后,还需要一层层往上移交处理,可能的处理有:安全性校验,binary 解析,model 创建,写 db,存入 cache,UI 展示,以及一些 edge cases(断网,用户 logout,disk full,OOM,crash,关机。。) 等等,项目的 feature 越多,网络层往上的处理出错的可能性就越大。
举个最简单的场景为例子:消息可靠抵达网络层之后,写db 之前 App crash(不稀奇,是 App 都会 crash),虽然数据在网络层可靠抵达了,但没存进 db,下次用户打开 App 消息自然就丢失了,如果不在业务层再增加可靠性保障,网络层面不会重发,那么意味着这条消息对于 Receiver 永远丢失了。
这个方案可以简单理解为,将TCP 的 Ack 流程再走一遍,在应用层也构建一个 Ack 消息,在应用层可靠性得到确认(一般以存入 db 为准,更准确说是事务提交成功的回调函数)之后再发送这个 Ack 消息,Server 收到应用层 Ack 消息之后才认为 Receiver 已收到,否则也采取某种策略重发消息。

具体到IM App 当中,接收端接受到 Server 的 Message,将 Message 存入 db,在确认回调里发送 Ack Receive 消息,Server 收到 Ack Receive 即认为消息已经可靠抵达,否则会在某个时机重新推送(比如客户端重连服务器时候 Pull,比如有新消息时 Server Push)。
这个方案和上面不同,但也是在应用层操作。我们个每个Message 分配一个 Seq ID,这个 Seq ID 对于单个用户的接受消息队列来说是连续的,如果 Message A 和 Message B 是相邻的,那么 MsgBSeqID = MsgASeqID + 1。每次存入 db 的时候更新 db 里的 LastReceivedSeqID,LastReceivedSeqID 即为上一条写入数据库消息的 Seq ID。
这么做的好处是,每次从网络层收到消息时,从db 里取出 LastReceivedSeqID,如果 LastReceivedSeqID = 新消息 Seq ID - 1,那么说明应用层消息时连续的没有发生丢失。还可以对收到的批量消息做预检测,检查消息队列里的 Seq ID 是否为联系的,只要存在任何一种不连续的 Seq ID 情况,就说明发送了丢失,此时接收端可以用 LastReceivedSeqID 从 Server 重新获取准确的接受消息队列。即时通讯聊天软件app开发可以加小蓝豆的v:weikeyun24咨询
这么做的好处是避免了每次都需要发送一条Ack 消息,坏处是应用层逻辑复杂之后,一旦出现 Seq ID 不连续的情况,会过度依赖于 refetch,难以分析问题出现的原因,refetch 一旦过于频繁,其流量损耗极有可能大于 Ack 消息的数据量。
消息的可靠抵达可以抽象为更一般意义上的可靠性问题,工程上总会碰到需要解决各种形式可靠性问题的场景,以经典计算机理论或者实践为基础来分析应用层的工程问题,可以举一反三,药到病除。
在工程上实践可靠性,需要线了解工程的每一个环节以及数据如何在各个环节流动,接下来才是分析每一个环节数据出错的可能性。检验可靠性的标准时「入袋为安」,存入db 或者以其他方式持久化到 disk 当中,这样才能保证客户端每次都能正确读取到消息。
另外,可靠性可以理解为两方面:
· 一是数据可靠抵达(没有任何中间数据被丢失);
· 二是正确抵达(没有乱序或者数据更改)。
其实理论上TCP 也不是 100% 可靠(数据有可能在传输时改变而无法被检测到),而是 100% 工程上可靠(数据改变而不被检测到时个极小概率的事件),这是另外一个有意思的话题其实理论上TCP 也不是 100% 可靠(数据有可能在传输时改变而无法被检测到),而是 100% 工程上可靠(数据改变而不被检测到时个极小概率的事件),这是另外一个有意思的话题。
相关文章:
从客户端的角度来看移动端IM即时通讯的消息可靠性和送达机制
如何确保IM 不丢消息是个相对复杂的话题,从客户端发送数据到服务器,再从服务器抵达目标客户端,最终在 UI 成功展示,其间涉及的环节很多,这里只取其中一环「接收端如何确保消息不丢失」来探讨,粗略聊下我接触…...
2023年java春招面试题及答案
2023年java春招面试题1、下面有关jdbc statement的说法错误的是?2、下面有关JVM内存,说法错误的是?3、下面有关servlet service描述错误的是?4、下面有关servlet和cgi的描述,说法错误的是?5、下面有关SPRIN…...
Django学习——基础篇(上)
一、Django的安装 pip install djangopython目录下出现两个文件 djando-admin.exe django django-admin.exe django 二、创建项目 1.命令行(终端) 1.打开终端 winR 输入cmd 2.进入项目目录 3.执行命令创建项目 2.Pycharm 两种方法对比 1.命令行创…...
研报精选230302
目录 【个股230302华西证券_比亚迪】系列点评五十四:迪“王”需求向上 出口“海”阔天空【个股230302华西证券_华利集团】下游去库存背景下承压,毛利率保持稳健【个股230302开源证券_恒顺醋业】公司信息更新报告:四季度业绩承压,期…...
Unity心得
- 将结果与因子颠倒的函数Mathf.InverseLerp非常实用 - at 10 meters, you want volume 1 - at 20 meters, you want volume 0 - volume InvLerp( 20, 10, distance ) - 显示HideFlags为Hide类型的物体 Resources .FindObjectsOf…...
TryHackMe-Binex
Binex 枚举计算机并获取交互式 shell。利用 SUID 位文件,使用 GNU 调试器利用缓冲区溢出并通过 PATH 操作获得根访问权限。 端口扫描 循例 nmap SMB枚举 题目给了提示:Hint 1: RID range 1000-1003 Hint 2: The longest username has the unsecure pa…...
外贸人如何写出优秀的开发信?附详细思路
如何写出优秀的开发信?最近做出口生意的客户都在抱怨,开发信的回复率越来越低,其实原因有很多,有时候并非自己的能力实在很欠缺。原因总结如图:第一:市场不景气这个就是就属于客观因素了,这也许…...
python自学之《21天学通Python》(18)——第21章 案例2 Python搞定大数据
“大数据(Big Data)”这个术语最早期的引用可追溯到apache org的开源项目Nutch。当时,大数据用来描述为更新网络搜索索引需要同时进行批量处理或分析的大量数据集。随着谷歌MapReduce和GoogleFileSystem (GFS)的发布&a…...
面试问题【数据库】
数据库数据库的三范式是什么drop、delete、truncate 分别在什么场景之下使用char 和 varchar 的区别是什么数据库的乐观锁和悲观锁是什么SQL 约束有哪几种mysql 的内连接、左连接、右连接有什么区别MyIASM和Innodb两种引擎所使用的索引的数据结构是什么mysql 有关权限的表都有哪…...
Allegro如何输出钻孔表操作指导
Allegro如何输出钻孔表操作指导 用Allegro做PCB设计的时候,需要输出钻孔表格,用于生产加工,如下图 如何输出钻孔表,具体操作如下 点击Manufacture点击NC...
消息队列 面试题 整理
消息队列 为什么要使用消息队列? 异步解耦:关注的是通知而非处理。 流量削峰:将短时间内高并发的请求持久化,然后逐步处理,削平高峰期的请求。 日志收集: 事务最终一致性 系统间的消息通信方式ÿ…...
【Java】对象比较大小
在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。Java实现对象排序的方式有两种: 自然排序:java.lang.Comparable定制排序:java.util.Comparator 规则:需要我们自定义根据对象的某个或某些属…...
发票自动OCR识别并录入模板 3分钟免费配置
要问整个公司里和数据打交道最多的职能,非财务莫属了吧。除了每天要处理大量财务数据外,还有发票录入的工作让财务陷入“易燃易爆炸”的工作状态。发票报销看似简单,但发票的类型有很多种,每种发票需要录入的信息也有差别。再加上…...
Dubbo 配置说明
dubbo:scan:base-packages: com.ut.msdasw.services.appservice //这个会扫描该包下得全部接口protocol: //这个主要是配置传输的协议和端口,只是一个协议name: dubbo port: 30032registry: //这里是服务注册中心的地址address: spring-cloud://localhost consum…...
英飞凌TCxxx实战系列01_Alarm处理
目录 1.概述2. Alarm内部处理2.1关联的寄存器2.2 Alarm设置case3. SMU外部处理3.1 关联的寄存器4. WDT Alarm的特殊处理4.1 看门狗超时测试4.2 RecoveryTimer相关的Alarm1.概述 当MCU运行出现问题,如MCU温度过高、过低,看门狗超时等会触发一个Alarm,当SMU收到Alarm信号后,…...
飞桨全量支持业内AI科学计算工具——DeepXDE!
AI技术在跨学科融合创新方面扮演着日益重要的角色,特别是在Al for Science领域,AI技术的发展为跨学科、跨领域的融合创新带来了巨大的机会。AI已成为一个关键的研究工具,改变了基础科学的研究范式。依托AI技术开发的科学计算工具,…...
【c++基础】
C基础入门统一初始化输入输出输入输出符输入字符串const与指针c和c中const的区别const与指针的关系常变量与指针同类型指针赋值的兼容规则引用引用的特点const引用作为形参替换指针其他引用形式引用和指针的区别inline函数缺省参数函数重载判断函数重载的规则名字粉碎C编译时函…...
语音识别技术对比分析
文章目录一、语音识别产品对比二、百度语音识别产品1、套餐及价格:2、官网3、调研结果三、华为语音识别产品四、阿里云语音识别产品1、套餐及价格:2、官网地址3、调研结果五、科大讯飞语音识别产品1、套餐及价格:2、官网3、调研结果六、有道语…...
Idea git 回滚远程仓库版本
目标 回滚远程仓库到特定版本。 将【添加test03】版本回滚到【行为型模式】版本。 回滚前的效果图 步骤 ①复制需要回滚到的版本的版本号 ②右键项目,选择Git-Repository-Reset Head ③Reset Type选择Hard;To Commit填入步骤①复制的版本号ÿ…...
vscode C++配置
program:调试入口文件的地址cwd:程序启动调试的目录miDebuggerPath:调试器的路径launch.json// { // // Use IntelliSense to learn about possible attributes. // // Hover to view descriptions of existing attributes. // /…...
DAMOYOLO-S在复杂遮挡下的实例分割效果展示:精准勾勒物体轮廓
DAMOYOLO-S在复杂遮挡下的实例分割效果展示:精准勾勒物体轮廓 最近在测试各种目标检测和分割模型时,我遇到了一个挺头疼的问题:当画面里的物体挤在一起、相互遮挡,或者只露出一小部分时,很多模型就“犯迷糊”了。检测…...
Z-Image-Turbo-rinaiqiao-huiyewunv 可视化流程设计:使用Visio绘制模型服务架构与数据流图
Z-Image-Turbo-rinaiqiao-huiyewunv 可视化流程设计:使用Visio绘制模型服务架构与数据流图 作为一名技术架构师,我经常需要向团队、客户或管理层解释一个复杂的系统是如何工作的。光靠文字描述,往往事倍功半。一张清晰的架构图或数据流图&am…...
放弃OpenVINO!在树莓派5上用Anaconda环境直接跑通YOLOv5摄像头检测
放弃OpenVINO!在树莓派5上用Anaconda环境直接跑通YOLOv5摄像头检测 树莓派作为嵌入式开发的明星产品,其第五代在性能上有了显著提升,4GB内存和2.4GHz四核处理器让它能够胜任更多AI推理任务。而YOLOv5作为目标检测领域的轻量级标杆,…...
Wnt/β-catenin信号通路在组织修复与再生中的关键作用
1. Wnt/β-catenin信号通路:细胞修复的"总指挥" 想象一下你手指被划伤后伤口愈合的过程,或者肝脏在受损后自我修复的神奇能力。这些看似平常的现象背后,其实隐藏着一个精密的分子调控网络——Wnt/β-catenin信号通路。这条通路就像…...
基于图像的深度学习与MVS三维重建全流程服务 支持远程部署定制 含pcl/c++/matlab...
基于图像的深度学习MVS三维重建全流程 可远程部署,可定制 点云pcl,c,matlab开发,基于图像三维重建,点云算法开发 只需要提供摄的图像,即可生成完整的三维模型(大小场景均可)上周去爬了个浙西的小众山&#…...
保姆级教程:在QT中配置qcustomplot实现热力图(含常见问题解决方案)
QT中qcustomplot热力图实战:从配置到交互优化的完整指南 第一次在QT项目中尝试用qcustomplot绘制热力图时,我被数据映射和实时刷新的问题困扰了整整两天。直到凌晨三点调试通过的那一刻,才真正理解这个强大可视化工具的精妙之处。本文将分享那…...
阿里图标库(Iconfont)的本地引入 详细步骤
阿里图标库(Iconfont)本地引入 Vue3 详细步骤(文字版) 一、准备工作 登录 Iconfont 官网 访问 Iconfont 官网,使用账号登录(若无账号需注册)。 选择图标并加入项目 在搜索框输入关键词&#x…...
终极指南:如何用Hammer.js为AR应用打造自然手势交互体验
终极指南:如何用Hammer.js为AR应用打造自然手势交互体验 【免费下载链接】hammer.js A javascript library for multi-touch gestures :// You can touch this 项目地址: https://gitcode.com/gh_mirrors/ha/hammer.js Hammer.js是一个强大的JavaScript库&am…...
OpenClaw安全防护指南:Qwen3-32B镜像对接时的权限控制策略
OpenClaw安全防护指南:Qwen3-32B镜像对接时的权限控制策略 1. 为什么需要安全防护? 去年我在尝试用OpenClaw自动整理财务报表时,曾因为一个简单的"读取桌面所有Excel文件"指令,差点导致包含客户隐私的文档被误传到测试…...
各行业开发经验全面解析,本凡科技助你快速提升项目成功率
在当今快速发展的市场中,各行业的开发经验已成为决定项目成败的关键因素。每个行业都面临独特的挑战和需求,了解这些特性有助于企业制定有效的开发策略。例如,科技行业通常需要快速响应市场变化,而食品行业则需关注合规性和安全标…...
