zoukankan      html  css  js  c++  java
  • MQTT服务质量等级及抓包分析

    什么是服务质量?
    服务质量(QualityofService,QoS)等级是消息发送方与消息接收方之间的协议,对应着消息传递时不同的可靠程度。
    MQTT有三种QoS等级:

    • 至多一次(QoS 0)
    • 至少一次(QoS 1)
    • 只有一次(QoS 2)

    MQTT中消息的发布和订阅都有QoS等级的设置,我们需要将其分开理解
    1.publish的QoS等级
    1.1 QoS 0
    当client1 publish一条消息时,如果设置的QoS等于0,那么client1只会发送一次这条消息,就算broker没有收到,client1也不会管。对于broker来说,它收到client1 publish的消息,就会PUBLISH给众多客户端,收不到自然也不会PUBLISH。产生的效果:broker最终会PUBLISH 0条或1条消息,即至多一次。
    publish

    1.2 QoS 1
    上面那个例子,如果设置QoS等于1,那么client1发送一条消息,broker收到后会发给client1一个应答PUBACK,client1如果收到应答就会停止发送,否则,继续发送。broker做的事情也很简单,收到一次消息,就将消息PUBLISH给众多客户端,同时发现QoS等级为1,就向刚刚给自己publish消息的client1发送一个响应PUBACK。但是在这种交互中存在两个问题,1:client1 publish的消息有可能broker没能收到,2:broker回复的PUBACK client1没能收到。这样会造成:broker收到消息,将消息PUBLISH出去后,client1没能收到PUBACK,就会继续发送消息,broker就会继续PUBLISH,直到client1收到PUBACK为止。产生效果:broker最终会PUBLISH 至少1条消息,即至少一次。
    publish QoS 1

    1.3 QoS 2
    还是上面的例子,如果设置QoS等于2,那么client1发送一条消息后,broker会回一个PUBREC(publish recevied)(但是这里注意broker虽然已经收到了消息但是它不会立马PUBLISH给众多客户端,还要等待后续步骤),client1收到PUBREC会回应一个PUBREL(publish release)(即既然你broker收到了,我client1就把这条消息释放了,保存起来太占地方),client1也不会再重复发这条消息了,因为都已经释放这个包了,broker收到PUBREL后会回复client1一个PUBCOMP(publish complete)(即这次消息传递完毕),broker发完PUBCOMP后,才会将刚才的消息PUBLISH给众多客户端。在PUBCOMP之前的交互中,如若有丢包同样会重传。产生效果:broker最终会PUBLISH 1条消息,不会多于1条,也不会少于1条。
    publish QoS 2

    应用场景:
    为什么要有这三种服务质量等级呢?我们结合具体需求来思考一下
    QoS 0 适合什么场景呢?适合那种消息很频繁但又不那么重要的应用,如每隔几分钟上报一次气温,数据丢了就丢了,反正待会还会上报,并且丢失一次数据也不会产生多大影响。
    但是,如果消息对你很重要,你宁愿收到重复的也不愿意丢失一条,那你就采用QoS 1
    但是,如果像支付类的应用也采用QoS 1的话,会产生重复支付的问题(其实已经支付成功了,只是手机没有收到回应,又再次发起支付),这时候就需要使用QoS 2了,它保证有且仅有一次消息成功传递。

    2.subscribe的QoS等级
    说完了publish的QoS,我们再来谈谈subscribe的QoS。其实我们完全可以使用上面三个例子的分析,因为clientA、clientB、clientC 订阅 broker的消息就相当于broker发布消息给他们(这点从后面的抓包分析也可得以验证),我们仍然可用publish的那一套去理解subscribe的QoS,即client A subscribe消息时设置的QoS等于0,那么broker最多只会发一次消息给clientA。QoS设置为1,那么broker至少会发一次消息给到clientA,给不到就重发。QoS设置为2,那么broker保证有且只有一次消息给到clientA。
    但是有一个问题需要注意一下,对于同一个topic,如果client1以QoS 2等级发布,clientA以QoS 0等级订阅,那么clientA最多只会收到一条消息,即两者质量等级取最低。同样的,如果clinet1以QoS 0发布一条消息,clientA以QoS 2等级去订阅,clientA仍然最多只会收到一条消息,因为原则是两者QoS取最低。所以如果要想达到真正的QoS 2质量,就要保证publish和subscribe都设置为 QoS 2

    3.抓包
    下面结合抓包做一些直观的展示
    192.168.2.195为客户端
    211.159.189.50为服务端
    3.1 connect 连接请求报文
    connect
    从截图中可以看出,MQTT是基于TCP的,MQTT连接前先进行的是TCP的三次握手建立TCP连接
    客户端通过发送MQTT连接控制报文向服务端发起连接请求,控制报文类型为0x10,可变长报头包含协议名、保活时间等信息,有效载荷包含客户端ID信息

    3.2 CONNACK – 确认连接请求

    服务端给客户端发送确认信息

    3.3 订阅请求


    3.4 订阅请求应答

    3.5 发布消息

    因为发布的消息服务质量等级为 QoS 0,所以无响应

    现在我们将publish 的服务质量等级设为 QoS 1

    再次抓包

    发现每一个publish的消息服务端都会有一个回应

    再将服务质量等级提升到 QoS 2

    抓包

    和上面分析的QoS 2一致,每次消息传递都需要四次交互,即(publish)Publish Message、(PUBREC)Publish Received、(PUBREL)Publish Release、(PUBCOMP)Publish Complete

    3.6 还想看一下subscribe的QoS

    我在客户端同时发布和订阅了相同的topic,服务质量等级都设为QoS 2,
    截图中,方框框住的上面四条为客户端向服务端publish消息时产生的交互,满足上面的QoS 2等级的分析。下面四条为客户端订阅了topic而收到消息时的交互,同时也验证了客户端订阅就相当于服务端发布的猜想。

    参考文章:https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels

  • 相关阅读:
    184. Department Highest Salary【leetcode】sql,join on
    181. Employees Earning More Than Their Managers【leetcode】,sql,inner join ,where
    178. Rank Scores【leetcode】,sql
    177. Nth Highest Salary【leetcode】,第n高数值,sql,limit,offset
    176. Second Highest Salary【取表中第二高的值】,sql,limit,offset
    118. Pascal's Triangle【LeetCode】,java,算法,杨辉三角
    204. Count Primes【leetcode】java,算法,质数
    202. Happy Number【leetcode】java,hashSet,算法
    41. First Missing Positive【leetcode】寻找第一个丢失的整数,java,算法
    删除
  • 原文地址:https://www.cnblogs.com/liyongjun/p/9657579.html
Copyright © 2011-2022 走看看