MQTT
(MessageQueuingTelemetryTransport
,消息队列遥测传输协议)是一种基于发布/订阅(publish
/subscribe
)模式的“轻量级”通讯协议,该协议构建于TCP/IP
协议上,由IBM在1999年发布。
MQTT最大优点在于,作为一种低开销、低带宽占用的即时通讯协议,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。使其在物联网、小型设备、移动应用等方面有较广泛的应用。
TCP/IP
参考模型可以分为四层:应用层、传输层、网络层、链路层。TCP
和UDP
位于传输层,应用层常见的协议有HTTP
、FTP
、SSH
等。**MQTT**
协议运行于**TCP**
**之上,属于应用层协议,**因此只要是支持TCP/IP
协议栈的地方,都可以使用MQTT
。
TCP/IP
提供网络连接;LastWill
和Testament
特性(最后遗嘱)通知有关各方客户端异常中断的机制。
ApplicationMessage
MQTT
协议通过网络传输应用数据;MQTT
传输时,它们有关联的服务质量(QoS
)和主题(Topic
)。Client
使用MQTT
的程序或设备。客户端总是通过网络连接到服务端。它可以:
Server
一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。它可以:
Subscription
TopicFilter
)和一个最大的服务质量(QoS
)等级;Session
)关联;TopicName
TopicFilter
Session
MQTTControlPacket
MQTT
规范定义了十四种不同类型的控制报文,其中一个(PUBLISH
报文)用于传输应用消息。MQTT
协议通过网络传输应用消息,应用消息通过MQTT
传输时,它们有关联的服务质量(QoS
)和主题(Topic
)。主题本质上是一个字符串,MQTT
协议规定主题是UTF-8
编码的字符串,这意味着,主题过滤器和主题名的比较可以通过比较编码后的UTF-8
字节或解码后的Unicode
字符。
MQTT
协议中规定了主题是一段UTF-8
编码的字符串,主题需要满足以下规则:
ACCOUNTS
和Accounts
是不同的主题名。Accountspayable
是合法的主题名/
区分。/finance
和finance
是不同的。/
的主题名或主题过滤器是合法的。null
字符(UnicodeU+0000
)。UTF-8
编码字符串,除了不能超过UTF-8
编码字符串的长度限制之外,主题名或主题过滤器的层级数量没有其它限制。
斜杠(“/”U+002F
)用于分割主题的每个层级,为主题名提供一个分层结构。分隔符用于将结构化引入主题名。如果存在分隔符,它将主题名分割为多个主题层级,是消息主题层级设计中很重要的符号。比方说:aaa/bbb
、aaa/bbb/ccc
和aaa/bbb/ccc/ddd
这样的消息主题格式,是一个层层递进的关系,可通过多层通配符同时匹配两者,或者单层通配符只匹配一个。这在现实场景中,可以应用到:公司的部门层级推送、国家城市层级推送等包含层级关系的场景。MQTT
订阅报文包含一个主题过滤器(TopicFilter
)和一个最大的服务质量(QoS
)等级。订阅的主题过滤器可以包含特殊的通配符,允许客户端一次订阅多个主题。当客户端订阅指定的主题过滤器包含两种通配符时,主题层级分隔符就很有用了。主题层级分隔符可以出现在主题过滤器或主题名字的任何位置。相邻的主题层次分隔符表示一个零长度的主题层级。
主题过滤器中可以使用通配符,但是主题名不能使用通配符。单层通配符和多层通配符只能用于订阅(
subscribe
)消息而不能用于发布(publish
)消息,层级分隔符两种情况下均可使用。
井字符号(“#”U+0023
)是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子层级。
例如,如果客户端订阅主题sport/tennis/player1/#
,它会收到使用下列主题名发布的消息:
sport/tennis/player1
sport/tennis/player1/ranking
sport/tennis/player1/score/wimbledon
因为多层通配符包括它自己的父级,所以sport/#
也匹配单独的sport
主题名,sport/tennis/player1/#
也可以匹配sport/tennis/player1
。
单独的多层通配符#
是有效的,它会收到所有的应用消息。
多层通配符必须单独指定,或者跟在主题层级分隔符后面。多层通配符必须是主题过滤器的最后一个字符。因此,sport/tennis#
和sport/tennis/#/ranking
都是无效的多层通配符。
加号(“+”U+002B
)是只能用于单个主题层级匹配的通配符。例如,sport/tennis/
+匹配sport/tennis/player1
和sport/tennis/player2
,但是不匹配sport/tennis/player1/ranking
。同时,由于单层通配符只能匹配一个层级,sport/
+不匹配sport
但是却匹配sport/
。
在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级,可以在主题过滤器中的多个层级中使用它,也可以和多层通配符一起使用,+
、+/tennis/#
、sport/+/player1
都有有效的。在使用单层通配符时,单层通配符占据过滤器的整个层级,sport+
是无效的。
\$
开头的主题服务端不能将$
字符开头的主题名匹配通配符(#
或``+)开头的主题过滤器,订阅#
的客户端不会收到任何发布到以$
开头主题的消息,订阅+/monitor/Clients
的客户端也不会收到任何发布到$SYS/monitor/Clients
的消息。服务端应该阻止客户端使用这种主题名与其他客户端交换消息,客户端注意不能使用$
字符开头的主题。
服务端实现可以将$
开头的主题名用作其他目的。,例如$SYS/
被广泛用作包含服务器特定信息或控制接口的主题的前缀。订阅$SYS/#
的客户端会收到发布到以$SYS/
开头主题的消息,订阅$SYS/monitor/+
的客户端会收到发布到$SYS/monitor/Clients
主题的消息,如果客户端想同时接受以$SYS/
开头主题的消息和不以KaTeX parse error: Expected 'EOF', got '#' at position 17: …头主题的消息,它需要同时订阅`#̲`和`SYS/#`。
比如我们用传感器监视家里的卧室、客厅以及厨房的温度、湿度和空气质量,可以设计一下几个主题:
myhome/bedroom/temperature
myhome/bedroom/humidity
myhome/bedroom/airquality
myhome/livingroom/temperature
myhome/livingroom/humidity
myhome/livingroom/airquality
myhome/kitchen/temperature
myhome/kitchen/humidity
myhome/kitchen/airquality
当我们想获取卧室的所有数据时,可以订阅myhome/bedroom+
主题,当我们想获取三个房间的温度数据的时候,可以订阅myhome/+/temperature
主题,当我们想获取所有的数据的时候,可以订阅myhome/#
或者#
。
QoS0
,At most once,至多一次;
QoS1
,At least once,至少一次;
QoS 2
,Exactly once,确保只有一次。PUBREC
消息发布收到。是对QoS
级别为2
的PUBLISH
消息的响应。它是QoS
级别2
协议流的第二个消息。PUBREC
消息由服务器响应来自发布端的PUBLISH
消息,或订阅端响应来自服务器的PUBLISH
消息。发布端或服务器收到PUBREC
消息时,会响应PUBREL
消息。
PUBREL
消息发布释放。是从发布端对PUBREC
的响应,或从服务器对订阅端PUBREC
消息的响应。这是QoS
级别2
协议流中第三个消息。当服务器从发布者收到PUBREL
消息时,服务器会将PUBLISH
消息发送到订阅端,并发送PUBCOMP
消息到发布端。当订阅端收到来自服务器的消息PUBREL
时,使得消息可用于应用程序并将PUBCOMP
消息发送到服务器。
PUBCOMP
消息发布完成。是服务器对来自发布端的PUBREL
消息的响应,或订阅者对来自服务器的PUBREL
消息的响应。它是QoS
级别2
协议流程中的第四个也是最后一个消息。当发布端收到PUBCOMP
消息时,它会丢弃原始消息,因为它已经将消息发给了服务器。
需要注意的是MQTT
发布与订阅操作中的QoS
代表了不同的含义:
QoS
表示消息发送到MQTT
服务器使用的QoS
等级;QoS
表示MQTTBroker
向自己转发消息时可以使用的最大QoS
等级。需要保障发送与订阅的**QoS**
一致,才能确保最终收到的消息是固定的**QoS**
等级,否则会出现消费降级的情况。例如:A
发送的消息QoS
为2
,B订阅的消息QoS
为1
,则最终接收到消息的QoS
为1
。
RetainedMessages
。MQTT
中,无论是发布还是订阅都不会有任何触发事件。1个Topic
只有唯一的retain
消息,Broker
会保存每个Topic
的最后一条retain
消息。发布消息时把retain
设置为true
,即为保留信息。每个Client
订阅Topic
后会立即读取到retain
消息。如果需要删除retain
消息,可以发布一个空的retain
消息,因为每个新的retain
消息都会覆盖最后一个retain
消息。
LastWill&Testament
。MQTT
本身就是为信号不稳定的网络设计的,所以难免一些客户端会无故的和Broker
断开连接。当客户端连接到Broker
时,可以指定LWT
,Broker
会定期检测客户端是否有异常。当客户端异常掉线时,Broker
就往连接时指定的Topic
里推送当时指定的LWT
消息。