对mqtt协议Qos2服务质量等级的理解

publish报文

publish报文的发生方向

发生的方向是:双向的,既可以从客户端发往服务器端,又可以从服务器端发往客户端。

客户端使用 PUBLISH 报文发送应用消息给服务端, 目的是分发到其它订阅匹配的客户端。
服务端使用 PUBLISH 报文发送应用消息给每一个订阅匹配的客户端。

publish报文的结构

固定报头:
   1、固定报头中的重发标志dup:
              如果是第一次发送此报文,则置dup=0
              如果是重发报文, 则置dup=1
  2、服务质量等级
               Qos=0
               Qos=1
               Qos=2
  3、保留标志
         保留标志的可选值:  retain=1    retain=0


可变报头:
  1、主题名 topicName
  2、报文标识符,只有当Qos=1或2时,pub报文中才有报文标识符
有效载荷
      由应用指定的数据

Qos1级别的publish报文

服务质量Qos1会确保消息至少送达一次。Qos1的publish报文的可变报头中包含一个报文标识符,需要pubAck报文确认。

对于Qos1的分发协议,发送者:

- 每次发送新的应用消息都分配一个未使用的报文标识符

- 发送的publish报文必须包含报文标识符且Qos等于1,dup等于0。

- 必须将这个publish报文看作是未确认的,直到从接收者那里收到对应的pubAck报文

对于Qos1的分发协议的接收者:

  • 响应的pubAck报文必须包含一个报文标识符,这个标识符来自接收到的,已经接收所有权的
    publish报文

  • 发送pubAck报文之后,接收者必须将任何包含相同报文标识符的入站publish报文当作一个新的
    消息,并忽略它的DUP标志的值

Qos1的协议的交互流程图

下面这张图是:Qos1的交互流程图:


mqttQos1报文交互 (3).jpg

Qos1级别的pub报文的缺陷

消息重复的问题

在上图中,我们可以看到,对于发送方来说,当它发送一个pub报文时,它会一直等待着来自对方(接收方)的消息确认报文pubAck。只有收到pubAck报文之后,它才认为该pub报文已经发送成功,否则,就会执行重试。
即: 再次发送该pub报文给客户端直到收到pubAck确认已经发生成功为止。

但是,这里有个问题,那就是: 如果接收方已经收到了pub报文,而且它也把pubAck报文发送出去了,但是由于网络状况太差或者其他原因,导致了这个pubAck报文丢失了,发送方接收不到来自接收方的pubAck确认报文。
于是,发送方就会对此pub报文进行二次重发,这样的话,接收方就又收到了一条和原来一模一样的pub报文,实际上由于接收方之前就已经收到并处理过该报文了,所以这次报文对接收方来说,就是一条重复报文。

可见,导致重复消息的原因就是: pubAck报文在网络传输中丢失造成的。

Qos2解决Qos1的重复消息问题

Qos2是最高的服务质量等级,消息丢失和重复都是不可接收的。但是使用这个服务质量等级会有额外的开销。

两步确认过程

Qos2的pub报文的接收者使用一个两步确认过程来确认收到。

发送方和接收方的处理

对于Qos2的发送方来说:

  . 必须要给要发送的新应用消息分配一个未使用的报文标识符。

  . 发送的pub报文必须包含报文标识符且报文的Qos等于2,dup等于0.

  . 必须将这个pub报文看作是未确认的,直到从接收者那收到pubRec报文。

  . 收到pubRec报文后必须发送一个pubRel报文,pubRel报文必须包含与原始的pub报文相同的报文标识符

  . 必须将这个pubRel报文看作是未确认的,直到从接收者那收到对应的pubComp报文

  . 一旦发送了对应的pubRel报文就不能重发这个publish报文了。

对于Qos2的接收者来说:

. 响应的pubRec报文必须包含报文标识符,这个标识符来自接收到的、已经接收所有权的publish报文。

. 在收到对应的pubRel报文之前,接收者必须发送pubRec报文确认任何后续的具有相同标识符的pub报文。

. 响应的pubRel报文的pubComp报文必须包含与pubRel报文相同的报文标识符

. 发送pubComp报文之后,接收者必须将包含相同报文标识符的任何后续的pub报文当做一个新的发布。  

Qos2的交互流程

mqttQos2报文交互 .jpg

我们知道,Qos1的消息重复问题的根源在于:pubAck报文的丢失导致。

所以,如果我们要解决消息的重复问题,就必须致力于解决 pubAck报文的丢失问题,在Qos2中,对应的就是pubRec报文的丢失问题。
即:确保发送方一定可以收到来自接收方的pubRec报文。所以这里就引出了:2步确认过程。

step1:  第一次使用应答机制来对pub报文进行确认,从而确保接收方一定可以接收到pub报文。

step2:  第二次使用应答机制来对pubRec报文进行确认,从而确保发送方一定可以接收到pubRec报文。

可见:

1、pubRec 是对pub的保证,确保pub不会丢失
2、pubRel 是pubRec的保证,确保pubRec不会丢失
3、pubComp是pubRel的保证,确保pubRel不会丢失


如果sender没有收到pubRec,就要重发该pub。

如果receiver没有收到pubRel,就会重发pubRec。

如果sender没有接收到pubComp,就会重发pubRel。


  • 对于接收方来说,收到pubRel报文之后,它的使命就完成了。(即: 它不仅收到了pub消息,而且确信自己也已把pubRec报文送到了发送方。)

  • 对于发送方来说,收到了pubRec报文,就意味着,pub报文已经被接收方确定接收了。收到了pubComp报文,就意味着,pubRel报文已经确定被接收方接收了。

你可能感兴趣的:(对mqtt协议Qos2服务质量等级的理解)