当前位置: 首页 > 科技观察

为什么微信不掉消息?

时间:2023-03-13 17:44:19 科技观察

上一章,我跟大家分享了《http如何像tcp一样实时的收消息?》。在本章中,我将讨论即时消息(IM)消息的可靠传递。1、消息类型im的客户端和服务端通过发送消息(即网络包)完成消息传递。消息分为三种:请求消息(request,以下简称R)和响应消息(acknowledge,以下简称A)通知消息(notify,以下简称N),这三种消息的解释是如下:R:客户端主动向服务器发送的消息A:服务器被动响应客户端的消息,一个A对应一个RN:服务器主动向客户端发送的消息2.普通消息传递流程用户A向用户B发送一个“Hello”,流程如下:1)client-A向im-server发送消息请求包,即msg:R2)处理成功后,im-server回复client-A带有消息响应包,即msg:A3)如果此时client-B在线,im-server会主动向client-B发送消息通知包,即msg:N(当然,如果client-B不在线,消息将离线存储)3.a中的问题从流程图中可以很容易地看出以上消息传递过程。发送方client-A收到msg:A后,只能说明im-server成功收到消息并不代表client-B已经收到消息。在某些场景下,msg:N包可能丢失,发送端client-A完全不知道,例如:1)服务器崩溃,msg:N包没有发送2)网络波动,msg:Npacketisdiscardedbythenetworkdevice3)client-Bcrash,msg:Npacketisnotreceived悲观的结论:接收方client-B是否已经收到msg:N,发送方client-A完全不可控,那又怎样我们应该做什么?4、应用层确认+Upd是不可靠传输层协议,tcp是可靠传输层协议。tcp是如何实现可靠性的?答案是:超时、重传、确认。为了在应用层实现消息的可靠传递,必须增加应用层的确认机制,即如果发送方client-A保证接收方client-B已经收到消息,则接收方client-B必须给出消息的确认,应用层确认过程与消息发送过程类似:4)client-B向im-server发送ack请求包,即ack:R5)im-server回复client-Bwith成功处理响应包后的ack,即ack:A6),则im-server主动向client-A发送ack通知包,即ack:N至此,发送“Hello”的client-A只能收到ack:N消息后发送。确认客户端B确实收到了“hello”。会发现一个消息的发送分别包括(上)(下)两半,即msg的三个R/A/N消息,ack的三个R/A/N消息,以及一个应用层real-time通信消息的可靠传递共涉及6条消息,是im系统中消息传递的核心技术。5.可靠的消息传递有哪些问题?预计6条消息就完成了消息的可靠传递,但实际上,消息msg:N和ack:N都可能丢失(原因如第2章所述,可能是服务器崩溃,网络抖动,或者clientcrash),此时client-A无法收到预期的ack:N报文,即client-A无法确认client-B是否收到了“Hello”,但是两者丢失对应的业务影响每条消息都大不相同:1)msg??:N个包丢失,业务结果是client-B没有收到消息2)ack:N个包丢失,业务结果是client-B收到了消息,是只是那个client-A不知道,怎么办?6.消息超时和重传Client-A发送msg:R,收到msg:A后,如果在预期时间内没有收到ack:N,client-A会尝试重发msg:R。client-A可能同时发送了很多消息,所以client-A需要在本地维护一个等待ack队列,配合timer超时机制记录哪些消息没有收到ack:N,以便于重发有规律的间隔。一旦收到ack:N,就说明client-B收到了“Hello”消息,相应的消息就会从“waitingackqueue”中移除。7、消息重传有哪些问题?第五章提到,msg:N和ack:N都有可能丢失:1)msg:N消息丢失,也就是说client-B之前根本没有收到“Hello”消息,超时和重传机制是非常有效2)ack:N报文丢失,说明client-B之前收到过“Hello”报文(但client-A不知道),超时重传机制会导致Client-B收到重复报文,所以我该怎么做?8、消息去重的解决方法也很简单。发送方client-A生成消息去重msgid,保存在“waitingackqueue”中。客户端B使用相同的msgid重传消息,以在不影响用户体验的情况下进行重复数据删除。9.其他1)以上设计理念由客户端重传,可以保证服务端的无状态(架构设计的基本原则)2)如果客户端-B不在线,im-server保存离线消息后,mustforgeack:Nsenttoclient-A10.总结1)im系统通过超时、重传、确认和去重等机制保证消息的可靠传递,不丢不重发2)A“Hello”发送,包括前半部分msg:R/A/N和ack:R/A/N6条消息后半部分3)im系统很难做到系统层面不丢包不重,只能在业务层面等级。来自微信公众号《建筑师之路》