MQTT协议

MQTT模型

MQTT特点

MQTT服务质量

MQTT报文

MQTT消息类型表

参考文献


MQTT协议

简单来说:MQTT是一个消息传输协议,不同的设备可以通过这个协议进行消息的稳定传输。

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的轻量级通讯协议,该协议构建于TCP/IP协议上。

MQTT作为一种轻量级、高效的通信协议,在物联网和各种低带宽不稳定网络环境下扮演着重要的角色。它为设备之间的通信提供了简单、可靠的解决方案,用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务

MQTT模型

MQTT的运作模型中,有三种角色:发布者、服务器和订阅者,其中发布者和订阅者可以身份互换。

mqtt协议和消息队列区别_mqtt协议和消息队列区别

简单来说就是一个消息队列,但是MQTT的特点是某些情况并不会存储消息,例如:发布者A发布一个消息,如果没有订阅者,那么这个消息就丢失了。

在实际应用中,担任服务器的角色可以是一个小型的计算机(例如树莓派)或者是一个大型的Internet服务器都行。

MQTT特点

轻量级

MQTT协议设计简单轻巧,数据包头部较小,使其在低带宽、高延迟的网络环境中运行效率高,可以对比HTTP协议,HTTP协议的数据报头较大,就算是不携带任何的数据,都有一定字节的大小,但是MQTT的报头只有一个字节。

发布-订阅模式

MQTT采用发布者(Publisher)和订阅者(Subscriber)模式,发布者负责将消息发布到特定的主题(Topic),而订阅者可以选择订阅感兴趣的主题,接收与之相关的消息。这种模式使得设备之间可以异步通信,降低了耦合性,适用于多个设备之间的实时通信。发布者发布消息后,不需要等待订阅者的响应,从而提高了系统的响应性能。

可靠性

MQTT支持消息的持久性传输,确保消息的可靠性,这在物联网应用中非常重要,MQTT可以通过控制可靠性级别来确保消息传递的可靠性。

安全性

MQTT支持使用TLS/SSL进行加密通信,确保数据传输的安全性。此外,MQTT还支持用户名和密码进行认证,保护客户端和服务器之间的通信安全。

MQTT服务质量

MQTT有一个服务质量级别的概念,QoS(Quality of Service levels),这个概念能保证消息更可靠的传输,简单来说就是增加了消息确认机制。

  1. QoS 0(最多一次,At most once):

这是最低的服务质量级别。在这种级别下,消息会被尽最大努力发送,但不会进行确认。发布者一次发布消息后,就不会知道消息是否已经到达订阅者,也不会知道是否有订阅者接收到消息。如果消息在传输过程中丢失或未能到达订阅者,发布者将不会得到任何通知,也不会有重发的机制。因此,这种级别适合对消息传递可靠性要求不高的场景,如传感器数据采集等。

  1. QoS 1(至少一次,At least once):

在QoS 1级别下,消息的确保传递,发布者会收到一个确认(PUBACK),以表示消息已经到达代理服务器。如果代理服务器未能将消息传递给订阅者,它会重试直到成功传递,并且确保发布者收到确认。这样可以确保消息至少传递一次,但可能会导致重复传递,因为发布者可能会收到多个确认。QoS 1适用于一些要求消息传递至少一次的场景,但可以容忍一些重复传递的应用。

  1. QoS 2(恰好一次,Exactly once):

QoS 2提供了最高的消息传递质量。在这种级别下,发布者会收到两个确认(PUBREC和PUBCOMP)。PUBREC表示消息已经到达代理服务器,PUBCOMP表示消息已经成功传递给订阅者。在这个级别下,确保消息只传递一次,并且没有重复传递。虽然QoS 2提供了最高的可靠性,但它也是最耗费资源的级别,因为需要多次的确认和处理。因此,QoS 2适用于对消息传递严格要求恰好一次的场景,如金融交易等。

MQTT报文

MQTT的报文分为三个部分,分别是固定报头、可变报头、有效负载(消息体),对应的英文是Fixed Header、Variable Header、Payload。可以联想HTTP协议,有请求协议、请求头、请求数据等等。

mqtt协议和消息队列区别_mqtt协议和消息队列区别_02

  

根据下图分析一下MQTT的三个组成部分,其中纵坐标代表的是字节数量、横坐标代表的是位数。

mqtt协议和消息队列区别_服务器_03

固定报头

固定报头(上图中第一行),分别由消息类型、DUP、可靠等级、RETAIN、剩余长度组成:

  • 消息类型

MQTT支持发送多种数据类型,这里用4位的无符号二进制数表示多种数据类型,4位二进制能表示十进制的16种(0-15)种消息类型,例如:0001代表十进制值为1的消息类型,表示:消息从客户端到服务器,并且是请求连接的消息。

  • DUP

标识位,发布消息的副本,如果设置为 1,则在下面的变长中增加MessageId,并且需要回复确认,以保证消息传输完成,但不能用于检测消息重复发送。

  • 可靠等级

QoS发布消息的服务质量,即:保证消息传递的次数

  • 00:最多一次,即:<=1
  • 01:至少一次,即:>=1
  • 10:一次,即:=1
  • 11:预留
  • RETAIN

发布保留标识,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它,如果设有那么推送至当前订阅者后释放。

  • Remain length

它表示了整个报文剩余部分的长度(不包括固定报头的长度)。

剩余长度字段使用了一种可变长度编码方式,可以占用1到4个字节。每个字节的最高位(bit 7)表示后续字节是否是剩余长度的一部分。如果最高位为1,表示后续字节也是剩余长度的一部分;如果最高位为0,则表示这是最后一个字节,不再是剩余长度的一部分。

可变报头

MQTT数据包中包含一个可变头,在固定报头和负载之间。它存储着各种不同类型消息特定信息,它的内容和格式取决于消息的类型和功能。例如,在固定头中的消息类型是CONNECT(十进制为1的数据类型),可变报头会含客户端的标识符、是否清除会话、心跳超时等信息。

有效负载(消息体)

这是报文的第三部分,它包含了实际的应用数据。有效负载的内容格式是由固定报文中的消息类型来决定的,它可以携带各种不同类型的数据,例如传感器数据、命令指令、文本消息等。MQTT中的每种消息类型在定义上都可以包含有效负载,但在实际使用中,并不是每个消息类型都携带有效负载

以下列举出了,携带Payload的消息类型:

注意:虽然这些消息类型可以携带有效负载,但并不是每次使用时都必须包含有效负载。是否携带有效负载取决于具体的应用需求和消息传递的目的。

  • PUBLISH(发布消息)消息:PUBLISH消息用于发布数据或信息到指定的主题(Topic)。它是MQTT中最常用的消息类型之一,可以携带有效负载,以传递实际的数据、信息或者命令。
  • SUBSCRIBE(订阅主题)消息:SUBSCRIBE消息用于向MQTT代理服务器订阅特定的主题。它通常携带有效负载,指示订阅者要订阅的主题和对应的服务质量级别。
  • SUBACK(订阅确认)消息:SUBACK消息用于确认订阅请求的结果。它通常携带有效负载,返回订阅主题和对应的服务质量级别。
  • UNSUBSCRIBE(取消订阅)消息:UNSUBSCRIBE消息用于向MQTT代理服务器取消订阅特定的主题。它通常携带有效负载,指示订阅者要取消订阅的主题。
  • PUBREC(发布接收)消息:PUBREC消息用于实现QoS级别为2的消息传递。它通常不携带有效负载,只是作为PUBLISH消息的确认,返回一个消息标识符。
  • PUBREL(发布释放)消息:PUBREL消息用于实现QoS级别为2的消息传递。它通常不携带有效负载,只是作为PUBREC消息的确认,返回一个消息标识符。
  • PUBCOMP(发布完成)消息:PUBCOMP消息用于实现QoS级别为2的消息传递。它通常不携带有效负载,只是作为PUBREL消息的确认,返回一个消息标识符。

MQTT消息类型表

下面是MQTT报文中,固定报头的消息类型对应表,方便查阅:

名称

值(十进制)

流方向

描述

Reserved

0

不可用

保留位

CONNECT

1

客户端到服务器

客户端请求连接到服务器

CONNACK

2

服务器到客户端

连接确认

PUBLISH

3

双向

发布消息

PUBACK

4

双向

发布确认

PUBREC

5

双向

发布收到(保证第1部分到达)

PUBREL

6

双向

发布释放(保证第2部分到达)

PUBCOMP

7

双向

发布完成(保证第3部分到达)

SUBSCRIBE

8

客户端到服务器

客户端请求订阅

SUBACK

9

服务器到客户端

订阅确认

UNSUBSCRIBE

10

客户端到服务器

请求取消订阅

UNSUBACK

11

服务器到客户端

取消订阅确认

PINGREQ

12

客户端到服务器

PING请求

PINGRESP

13

服务器到客户端

PING应答

DISCONNECT

14

客户端到服务器

中断连接

Reserved

15

不可用

保留位

参考文献

  • MQTT 协议 3.1.1 中文版