MQTT之QOS机制分析

MQTT之QOS机制分析

QOS:quality of service,即 “质量服务”。

质量服务

质量:通讯质量,即 “消息的可靠性”
服务:保证消息可靠的机制

小编的测试、分析环境

MQTT服务端使用的EMQ,服务器系统Centos7.5

阅读前提

1、 首先必须要了解MQTT是做什么用的。
2、 其次最起码要搭建过一个MQTT的服务端起来,下载一个客户端,发布/订阅玩一下。

小编推荐体验MQTT的环境:MQTT服务端推荐EMQ,MQTT客户端推荐paho。
好吧,没链接推荐个毛,对吧…

EMQ: http://www.emqtt.com/
paho: https://www.eclipse.org/paho/components/tool/

QOS等级

QOS0::至少0次,大白话就是只管发,不管收。
QOS1::至少1次。
QOS2: 刚好1次(这个是很多书、资料上的说法,其实这里更准确的说法应当是 “保证相同的消息只接收一条”)。

以上的次数指的均是 “接收方” 接收到数据的次数,即,Broker/Server、Subscriber。(除了Publisher不需要接收,服务端和订阅端均需要接收的嘛)

多提一嘴(可跳过),显然,从上面的QOS等级可以看出来:
1、QOS0不可靠,因此适合大量数据的传输,因为很大量的数据,完全避免不丢包是很难的,网络环境、现实环境什么的。想要保证的话,大量的数据,一般是要做断点续传。而且小编的经验,像类似 “轮询” 这样不断地得到一些检测数据,这种数据,中间丢几包是基本不会影响业务的。
2、QOS1可靠,一般的场景够用,因为总能接到数据嘛。缺点就是 “可能造成” 1条数据,接了多次。
3、QOS2严格可靠,保证相同的消息只接收一条,(请稍微构思一下内部的实现…虽然不复杂,但要一定的流程来保证的,对吧),在每一次通讯都这样执行的话,势必会造成性能的考验,因此小编对QOS2的意见是 “如非必要,慎用,特别是个人/小团队,没有那么多资金租用特别好的服务器”。

Publisher与Subscriber的QOS组合

QOS等级是可以设置在 发布端(Publisher)订阅端(Subscriber) 的。
因此,不同的设置组合,会有不同的效果。

小编来列一下这个组合(发布端:P、订阅端:S)

P(QOS0)、S(QOS0)
P(QOS0)、S(QOS1)
P(QOS0)、S(QOS2)

P(QOS1)、S(QOS0)
P(QOS1)、S(QOS1)
P(QOS1)、S(QOS2)

P(QOS2)、S(QOS0)
P(QOS2)、S(QOS1)
P(QOS2)、S(QOS2)

虽然理论上有以上这些组合,但是EMQ的服务端认为订阅端的QOS等级要基于发布端的QOS等级,
大白话就是 if( S(QOS) > P(QOS) ) { S(QOS) = P(QOS) ;}
,即:

P(QOS0)、S(QOS2) == P(QOS0)、S(QOS1) == P(QOS0)、S(QOS0)
P(QOS1)、S(QOS2) == P(QOS1)、S(QOS1)

实际上的组合是这样子的:

P(QOS0)、S(QOS0)
P(QOS1)、S(QOS0)
P(QOS1)、S(QOS1)
P(QOS2)、S(QOS0)
P(QOS2)、S(QOS1)
P(QOS2)、S(QOS2)

WireShark证实这一切

ip地址说明:
发布端(Publisher):192.168.126.1
EMQ服务端(Broker/Server):192.168.126.130
订阅端(Subscriber):192.168.126.128

P(QOS0)、S(QOS0):
P(QOS0)、S(QOS0)的截图
P(QOS0)、S(QOS1):
P(QOS0)、S(QOS1)的截图
P(QOS0)、S(QOS2):
MQTT之QOS机制分析_第1张图片
以上三张图,证明P(QOS0)、S(QOS2) == P(QOS0)、S(QOS1) == P(QOS0)、S(QOS0)

P(QOS1)、S(QOS0) :
P(QOS1)、S(QOS0) 的截图
P(QOS1)、S(QOS1) :
MQTT之QOS机制分析_第2张图片
P(QOS1)、S(QOS2) :
P(QOS1)、S(QOS2)的截图
以上三张图,证明P(QOS1)、S(QOS2) == P(QOS1)、P(QOS1)

P(QOS2)、S(QOS0):
MQTT之QOS机制分析_第3张图片
P(QOS2)、S(QOS1):
MQTT之QOS机制分析_第4张图片
P(QOS2)、S(QOS2):
MQTT之QOS机制分析_第5张图片


总结

从以上的wireshark抓包截图,可以看出

QOS0: sender只向receiver发一次包,无论receiver能不能够收到。因此结论为receiver “至少0次或至多1次收到(相同内容/同一份)数据包” 。

QOS1:sender向receiver发包,如果receiver收到数据包,则回复sender,如果sender没有收到receiver的回复(就算已经成功发送了),则认为发生了丢包,会重发。因此结论为receiver “至少1次收到(相同内容/同一份)数据包” 。

QOS2:sender向receiver发一份(带有标识符)的数据包,如果receiver收到了数据包,则回复sender,如果sender没有收到receiver的回复(就算已经成功发送了),与QOS2不同的是,sender再次重发的数据包,会在receiver处先检查标识符,如果该数据包已缓存了,则丢弃sender重发的包,并重新回复sender,直到sender收到receiver的回复,sender再次发Publish Receive包到receiver,receiver收到之后回复Publish Complete包给sender,如此一套流程标志着此次通讯的完成。因此结论为receiver “刚好或只收到1次相同内容/同一份)数据包” 。

QOS1和QOS2的差异在于QOS2的数据包带有标识符,并且receiver需要收到sender再发的Publish Receive包,以确定消息收到的事实已被sender得知,最后以向sender回复Publish Complete来标志着此次通讯的完整、可靠。

你可能感兴趣的:(C/C++,Java,C#)