服务质量
MQTT按照这里定义的服务质量 (QoS) 等级分发应用消息。分发协议是对称的,客户端和服务端既可以是发送者也可以是接收者。分发协议关注的是从单个发送者到单个接收者的应用消息。服务端分发应用消息给多个客户端时,每个客户端独立处理。分发给客户端的出站应用消息和入站应用消息的QoS等级可能是不同的。
MQTT定义了三个层次的服务质量:
l QoS 0:最多分发一次;
l QoS 1: 至少分发一次;
l QoS 2: 仅分发一次
接下来,我们分别对这三个服务质量做特别的说明。
2.2.3.1 QoS 0,最多分发一次
消息的分发依赖于底层网络的能力。接收者不会发送响应,发送者也不会重试。消息可能送达一次也可能根本没送达。这个服务质量常用在鸡肋的消息传递中,即消息丢了也没有关系。
l 发送者:
必须发送QoS等于0,DUP等于0的PUBLISH报文。
l 接收者:
接受PUBLISH报文时同时接受消息的所有权。
l 使用场景:
尽力而为。
常用于广播。
l 交互方式:
l 断开重连
对于QoS 0的消息,在消息交互的过程中,如果出现断开重连的情况,丢失的消息报文也无需做特别的处理。
2.2.3.2 QoS 1,至少分发一次
服务质量确保消息至少送达一次,有可能存在多次发送的情况。
QoS 1的PUBLISH报文的可变报头中包含一个报文标识符,需要PUBACK报文确认。即需要接收者发送PUBACK回包,但是PUBACK回包只是用来重用相同的报文标识符,不影响后续非重复的报文标识符的发送。
l 发送者:
ü 每次发送新的应用消息都必须分配一个未使用的报文标识符。一旦发送者收到PUBACK报文,这个报文标识符就可以重用。
ü 发送的PUBLISH报文必须包含报文标识符且QoS等于1,DUP等于0。
ü 必须将这个PUBLISH报文看作是未确认的,直到从接收者那收到对应的PUBACK报文。
ü 允许发送者在等待确认时使用不同的报文标识符发送后续的PUBLISH报文。也就是说可以是异步的情况。
l 接收者:
ü 响应的PUBACK报文必须包含一个报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。
ü 发送了PUBACK报文之后,接收者必须将任何包含相同报文标识符的入站PUBLISH报文当作一个新的消息,并忽略它的DUP标志的值。简单的理解是,在发送PUBACK报文之后,如果还是接收到了一个相同的报文标识符,接收方应当认为这是一个新的报文,同时不关注DUP标志位的数值。
l 使用场景:
保证送达,可能重复
l 交互方式:
Client[Qos=1,DUP=0/*重复次数*/,MessageId=x]--->PUBLISH--> Server收到后,存储Message,发布,删除,向Client回发PUBACK。
Client收到PUBACK后,删除Message;如果未收到PUBACK,设置DUP++,重新发送,Server端重新发布,所以有可能重复发送消息。
l 断开重连
如果在消息分发的过程中出现了断开重连的情况,且客户端设置清理会话(CleanSession)标志为0重连时,客户端和服务端必须使用原始的报文标识符重发任何未确认的PUBLISH报文(如果QoS>0)和PUBREL报文。
且发送端重发任何之前的PUBLISH报文时,必须按原始PUBLISH报文的发送顺序重发。
接收端必须按照对应的PUBLISH报文的顺序发送PUBACK报文。
2.2.3.3 QoS 2,仅分发一次
这是最高等级的服务质量,消息丢失和重复都是不可接受的。使用这个服务质量等级会有额外的开销。
QoS 2的消息可变报头中有报文标识符。QoS 2的PUBLISH报文的接收者使用一个两步确认过程来确认收到。
l 发送者:
ü 必须给要发送的新应用消息分配一个未使用的报文标识符。一旦发送者收到PUBCOMP报文,这个报文标识符就可以重用。
ü 发送的PUBLISH报文必须包含报文标识符且报文的QoS等于2,DUP等于0。
ü 必须将这个PUBLISH报文看作是未确认的 ,直到从接收者那收到对应的PUBREC报文。
ü 收到PUBREC报文后必须发送一个PUBREL报文。PUBREL报文必须包含与原始PUBLISH报文相同的报文标识符。
ü 必须将这个PUBREL报文看作是未确认的 ,直到从接收者那收到对应的PUBCOMP报文。
ü 一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文。
l 接收者:
ü 响应的PUBREC报文必须包含报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。
ü 在收到对应的PUBREL报文之前,接收者必须发送PUBREC报文确认任何后续的具有相同标识符的PUBLISH报文。 在这种情况下,它不能重复分发消息给任何后续的接收者。
ü 响应PUBREL报文的PUBCOMP报文必须包含与PUBREL报文相同的标识符。
ü 发送PUBCOMP报文之后,接收者必须将包含相同报文标识符的任何后续PUBLISH报文当作一个新的发布。
l 使用场景:
不重复不丢失,是最理想的网络收发状态。
l 交互方式:
l 断开重连
如果在消息分发的过程中出现了断开重连的情况,且客户端设置清理会话(CleanSession)标志为0重连时,客户端和服务端必须使用原始的报文标识符重发任何未确认的PUBLISH报文(如果QoS>0)和PUBREL报文。
且发送端重发任何之前的PUBLISH报文时,必须按原始PUBLISH报文的发送顺序重发。
接收端必须按照对应的PUBLISH报文的顺序发送PUBREC报文。
发送端必须按照对应的PUBREC报文的顺序发送PUBREL报文。
2.2.3.4 几种QoS之间的关系
在MQTT3.1.1协议的设计过程中,涉及到QoS的报文信息包括以下几个类型:订阅,订阅确认,消息发布,消息分发。
1)订阅和订阅确认中的QoS
订阅是客户端向服务器端申请主题的行为,在每一个订阅报文中,为每一个订阅的主题指定了最大的QoS等级。而服务器端收到订阅请求之后,可以决定给每一个订阅主题的开放何种等级的QoS,并通过SUBACK告知客户端。
即订阅QoS >= 订阅确认QoS
2)消息发布和消息分发
消息发布通过PUBLISH报文实现,可能是服务器端到客户端,也可能是客户端到服务器端。如果是第二种情况的话,那就还需要服务器端根据订阅主题列表,还确认是否将该报文分发,于是就产生了消息分发的动作,在消息分发的报文中,也是包含有QoS的。
于是就涉及到发布消息的QoS,客户端收到订阅确认的QoS等级,以及分发消息(客户端收到消息)的QoS。那这三个之间的关系是如何呢?
一个简单的原则就是:第三个QoS是前两个QoS中的最小者。
列表如下:
发布消息的QoS |
Topic订阅确认的QoS |
分发消息(接收消息)的QoS |
0 |
0 |
0 |
1 |
0 |
0 |
2 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
2 |
1 |
1 |
0 |
2 |
0 |
1 |
2 |
1 |
2 |
2 |
2 |
版权所有,转载请注明出处:http://www.junsion.icoc.bz/ by 小丑
转载自原文链接, 如需删除请联系管理员。
原文链接:MQTT协议_服务质量,转载请注明来源!