微信为什么不丢消息?

上一章和大家分享了《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. **优化消息同步机制**:企业微信消息同步依赖于数据版本号实现增量同步,这一机制能够确保消息的可靠送达。为了消息丢失,可以进一步优化该机制,例如通过增加消息确认机制,确保每条消息在发送后都能得到接收端的确认回复,若未收到确认,则进行重传。[^1] 2. **增强通信稳定性**:消息丢失也可能由通信模块的稳定引起,如WIFI模块(ESP8266)和蓝牙模块(HC05)在连接和数据传输过程中的稳定、包或延迟等问题。对此,可以通过优化无线通信协议、增强信号质量、设置合理的重传机制等方式来解决。此外,针对网络环境的变化,可以采用如MQTT等低功耗物联网协议,以提高通信的稳定性和效率。[^2] 3. **合理设置消息优先级**:企业微信同类型的消息具有同的优先级,例如单聊群聊消息优先级最高,而控制消息的优先级最低。智能机器人在处理消息时,应根据消息的优先级进行排序处理,优先处理高优先级的消息,同时对于低优先级的消息,也应设计合理的处理策略,避免因处理当导致消息丢失。[^3] 4. **实现消息的持久化存储**:为止因系统故障或网络中断等原因导致的消息丢失,可以在消息发送前将其持久化存储到数据库或文件系统中,待消息成功发送并得到接收方确认后再从存储中删除。这样即使在发送过程中遇到问题,也可以通过查询存储记录来恢复消息,保证消息的完整性和可靠性。 5. **加强异常处理机制**:智能机器人应该具备强大的异常处理能力,能够在检测到消息发送失败或接收异常时,自动采取相应的补救措施,如自动重发、切换通信通道等,以减少消息丢失的可能性。 6. **定期维护和监控**:定期对智能机器人的运行状态进行检查和维护,及时发现并解决问题。同时,建立完善的监控体系,对消息的发送、接收及处理过程进行全程跟踪,以便快速定位问题原因并采取有效措施。 综上所述,通过优化消息同步机制、增强通信稳定性、合理设置消息优先级、实现消息的持久化存储、加强异常处理机制以及定期维护和监控等方法,可以有效地解决企业微信智能机器人在消息丢失方面的回复交互问题,提升系统的稳定性和用户体验。 ```python # 示例代码:消息确认机制的简单实现 def send_message(message): # 发送消息 print(f"发送消息: {message}") # 模拟消息发送后的确认过程 confirmation = input("是否收到消息确认?(y/n): ") if confirmation.lower() != 'y': # 如果未收到确认,进行重传 print("未收到确认,正在重传...") send_message(message) else: print("消息确认成功,处理下一个消息。") # 调用示例 send_message("你好,这是一个测试消息。") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值