lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1846 随笔 :: 0 文章 :: 109 评论 :: 288万 阅读

 

即时通讯(Instant Messaging,后简称im)消息的可靠投递

一、报文类型

  im的客户端与服务器通过发送报文(也就是网络包)来完成消息的传递

  报文分为:    

    请求报文(request,后简称为为R)--- 客户端主动发送给服务器的报文

    应答报文(acknowledge,后简称为A)--- 服务器被动应答客户端的报文,一个A对应一个R

    通知报文(notify,后简称为N)--- 服务器主动发送给客户端的报文

二、普通消息投递流程

  消息的发送流程:client-A给client-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包未接收

三、应用层确认+im消息可靠投递的六个报文

upd是一种不可靠的传输层协议,tcp是一种可靠的传输层协议,tcp的可靠是用超时、重传、确认实现的

要实现应用层的消息可靠投递,加入应用层的确认机制

应用层的确认的流程:想让发送方client-A确保接收方client-B收到了消息,必须让接收方client-B给一个消息的确认

存在的问题:msg:N,ack:N这两个报文都可能丢失

对业务的影响:

  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,以定时重发

  一旦client-A收到了ack:N,说明client-B收到了消息,对应的消息将从“等待ack队列”中移除

存在的问题:

  msg:N,ack:N有可能丢失,超时与重传机制将导致client-B收到重复的消息

五、消息的去重

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

说明:

  由客户端重传,可以保证服务端无状态性

  如果client-B不在线,im-server保存了离线消息后,要伪造ack:N发送给client-A

总结:

  im系统是通过超时、重传、确认、去重的机制来保证消息的可靠投递,不丢不重

  消息的发送,包含上半场msg:R/A/N与下半场ack:R/A/N的6个报文

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

posted on   白露~  阅读(2002)  评论(0编辑  收藏  举报
编辑推荐:
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示