MQTT-QoS与协议流程

发布时间 2023-04-28 17:54:46作者: 木子七

QoS的报文收发流程


QoS 0

最多交付一次,消息有可能丢失,最低的QoS等级,没有任何的机制,不需要等待确认和重传,只要保证消息发送,也可能到达不了接收端

QoS0消息发送流程:

  1. 发送端调用API发送消息
  2. 消息将被拷贝内核层的至发送缓冲区中
  3. 发送缓冲区的消息会在合适的时机被发送到网络中
  4. 经过路由跳转以后,消息被接收端的网卡接收,然后消息来到接收端的接收缓冲区
  5. 接收缓冲区有了消息,接收端的内核层就会通知上层应用读取消息

只有上层应用读取到了消息,消息才算真正到达了接收端,在之前的任意步骤出现网络断开,这些传输消息就会丢失,这也是消息可能丢失的原因

QoS 1

至少交付一次,消息有可能重复,为了解决消息丢失的问题,QoS 1 引入了重传机制

当我们使用QoS 1 消息的时候,每个PUBLISH的报文,都必须有一个接收端的PUBACK的报文作为响应,以确认接收对收到了消息,如果一直没有响应,发送端就会在特定时刻重新发送没有响应的消息,在PUBLISH中需要有Packet ID字段来作为该消息的唯一标识,而PUBACK响应中,也会包含收到消息相同的Packet ID,这样发送端在收到PUBACK报文时,就可以确认是哪条消息到达了

通过QoS 1 的重传机制,我们可以保证消息到达了,但是也不可能避免有了消息重复的可能性

当发送端因为没有收到响应报文重传的时候,可能接收端已经收到了消息并且回复了响应报文,但是响应报文可能因为网络断开等其他原因丢失了,这种情况下发送端再发送消息,接收端就收到了重复消息,虽然发送端在重传发送消息的时候会把DUP设置为1表示这是重传的消息,但是接收端也不能确定自己层级是否接受过该消息,会把消息当全新消息处理

如何为QoS 1 去重

虽然在协议层面我们没办法避免消息的重复,但是可以从业务的层面入手对消息进行去重,一个简单的方法是在每个PUBLISH报文的payload中携带一个时间戳或者单调递增的计数,这样业务层就可以根据时间戳或者计数是否大于上一次收到消息的时间戳or技术,来判断是不是新消息

重传不等于乱序

虽然发生了重传,但是不表示消息会乱序到达,我们发送了A、B、C三条消息,如果是A重传,就是 A、A、B、C ,如果A、B重传,就是A、B、A、B、C等等,不可能出现B、A、C这种情况

QoS 2

仅交付一次,消息不会重复也不会丢失,QoS 2也有这三种模式最复杂的报文交互,想要完成QoS 2的消息传递,最少要完成两次的请求响应流程,带来额外的性能开销

QoS2的报文

  • PUBLISH

    发布报文

  • PUBREC

    PUBLISH和RECEIVE的缩写,表示收到了PUBLISH报文

  • PUBREL

    PUBLISH 和RELEASE的缩写,表示准备释放这次的QoS2消息

  • PUBCOMP

    PUBLISH和COMPLETE的缩写,表示这一次QoS2的消息的发布即将完成

为什么QoS2的报文不会重复

​ QOS 2 使用PUBLISH和PUBREC报文来保证消息的到达,原理和QoS1一致,新增的PUBREL和PUBCOMP来保证消息不会重复,QoS2规定,发送端只有在收到PUBREC报文之前,才可以重传PUBLISH报文,而一旦收到了PUBREC报文并且发出了PUBREL报文,发送端就进入了Packet ID的释放流程,在收到接收端的PUBCOMP响应之前,发送端既不会使用该Packet ID重传消息,也不能用于发布新的消息,只有收到PUBCOMP响应之后,发送端才可以继续使用这个Packet ID,对于接收端来说,可以以PUBREL为界限,凡是PUBREL之前到达的PUBLISH报文,必然是重复的消息,PUBREL之后到达的消息,全是全新的消息

分发QoS2的消息

​ 如果接收端必须等到QoS2流程结束才能向后分发消息,如果网络不好的情况下,消息的实时性会受到很大影响,所以MQTT允许接收端第一次收到PUBLISH报文的时候,就启动消息的向后分发,一旦分发过之后,后续再收到重传报文,接收端就不能再进行分发操作了,以免消息操作

何时重传消息

​ 在QoS0和Qos1中,都有可能存在消息的重传,这里的重传并不是指超时的重传,在TPC连接内重传消息,并不会带来额外的收益,在网络不佳的情况下,反而可能降低消息的传输效率,也可能导致报文的收发流程异常,所以MQTT要求,只有在每次连接断开重连后,发送端才能重传上一次连接内没有收到响应的消息

不同的QoS的适用场景

QoS 0

  • 优点:投递效率高
  • 缺点:消息可能丢失
  • 适用场景:传输高频且不是那么重要的数据

QoS 1

  • 优点:保证消息到达
  • 缺点:消息可能重复
  • 适用场景:传输较为重要的数据,需要注意业务需要能够处理重复消息,或者能够允许重复消息

QoS 2

  • 优点:保证消息到达且不会重复
  • 缺点:拥有较高的开销
  • 适用场景:传输重要数据,并且能够接受QoS 2带来的额外的开销