目录
概述
1 认识MQTT
1.1 MQTT的定义
1.2 MQTT实现原理
1.3 MQTT架构的几个概念
1.3.1 MQTT Broker
1.3.2 MQTT Client
1.3.3 发布消息
1.3.4 订阅消息
2 认识MQTT报文结构
2.1 MQTT消息体结构
2.1.1 认识主题(Topic)
2.1.2 认识QoS(Quality of Service levels)
2.1.3 保留标志(retained)
2.2 MQTT心跳包
2.3 MQTT遗嘱机制
2.4 MQTT 用户认证
3 体验MQTT
概述
本文详细介绍了MQTT相关的概念,报文结构内容。还详细对MQTT Message的消息结构体的内容进行分析,介绍每一个参数的具体含义和用法。最后使用EMQX和MQTT.fx工具搭建了一个MQTT工作机制的测试平台,便于深入体验和理解MQTT的运行原理。
1 认识MQTT
MQTT详细协议文档,参看:
https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718061
1.1 MQTT的定义
MQTT(Message Queuing Telemetry Transport) 是一种基于客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。
下表总结一些MQTT协议的特点:
特点 | 描述 |
---|---|
实现方式 | 客户端-服务器的消息发布/订阅传输协议,可实现一对多的消息发布 |
复杂程度 | MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。 在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT) |
版本信息 | MQTT3.1.1 和 MQTT5 |
QoS 服务质量等级 | 根据消息的重要性不同设置不同的服务质量等级 |
资源消耗 | 小型传输, 开销很小,协议交换最小化,以降低网络流量。 |
1.2 MQTT实现原理
MQTT 是一种基于Client------Server架构的消息传输协议,所以,在 MQTT 协议通信中,所有的Client必须经过Server才能进行通信。其基本架构如图一所示,对Broker而言,所有Client的地位都是平等的,其发布或者订阅消息,必须经过MQTT Broker处理,才能实现。
图一 MQTT通信架构图
1.3 MQTT架构的几个概念
1.3.1 MQTT Broker
MQTT Broker是一种消息传递代理服务器,它实现了MQTT协议并提供了消息传递的功能。
MQTT Broker主要有以下几个功能和特点:
-
发布/订阅模式:MQTT Broker支持发布者(publishers)将消息发布到特定的主题(topics),订阅者(subscribers)可以订阅特定的主题来接收消息。这种发布/订阅模式使得消息传递更加灵活和可扩展。
-
轻量级:MQTT Broker的协议设计非常轻量级,占用的带宽和资源较少。这使得MQTT Broker非常适合在资源受限的设备和网络条件下使用,如物联网设备和低带宽网络等。
-
可靠性:MQTT Broker提供了一些可靠性保证机制,如QoS(Quality of Service)等级。QoS级别分为0、1和2三个级别,提供了不同的消息传递保证和可靠性。
-
扩展性:MQTT Broker可以支持大量的发布者和订阅者,并且支持多种不同的消息传递场景。通过合理的架构设计和配置,可以实现高可扩展性和高并发性。
-
安全性:MQTT Broker支持基于用户名和密码的身份验证,以及TLS/SSL等加密通信方式,保证消息传递的安全性。
-
灵活性:MQTT Broker可以与其他系统和服务进行集成,如消息队列、数据库和Web应用等。这使得MQTT Broker在各种应用场景中都能灵活使用。
1.3.2 MQTT Client
MQTT Client是一种实现了MQTT协议的客户端库或软件,用于连接MQTT代理(也称为MQTT服务器)并进行发布和订阅消息的操作。MQTT Client可以是嵌入式设备上的软件库,也可以是计算机或移动设备上的独立应用程序。
MQTT Client提供了许多功能和接口,使开发人员可以轻松地使用MQTT协议进行通信。一般来说,MQTT Client具有以下主要功能:
-
连接管理:MQTT Client可以与MQTT代理建立稳定的网络连接并维持心跳保持活动状态。
-
认证和安全性:MQTT Client可以提供认证机制,确保只有经过授权的设备可以连接和发送消息。同时,它还可以支持加密传输,保护消息的机密性。
-
发布和订阅消息:MQTT Client可以发布消息到指定主题(Topic)或订阅特定主题来接收消息。它可以支持不同的消息质量等级,如最多一次、至少一次和只有一次。
-
消息保留:MQTT Client可以选择将消息保留在服务器上,以便新的订阅者能够获取最新的消息。
-
遗嘱消息:MQTT Client可以设置一个遗嘱消息,以便在连接异常断开时,代理可以将该消息发送给所有订阅者。
-
QoS级别:MQTT Client可以选择消息的传输质量等级(Quality of Service),以确保可靠的消息传递。
-
异步通信:MQTT Client可以使用异步机制来处理消息,以避免阻塞主线程。
1.3.3 发布消息
MQTT采用发布-订阅模式,其中消息的发布方被称为发布者,而消息的接收方被称为订阅者。
要发布消息到MQTT中,首先需要连接到MQTT代理(broker)。连接时需要提供代理的地址和端口号,并且可以选择是否使用安全连接(例如使用TLS/SSL)。
连接成功后,发布者可以选择一个主题(topic)来发布消息。主题是消息的分类标签,订阅者可以根据主题来过滤接收到的消息。发布者可以将消息内容以及主题信息发送给MQTT代理,代理负责将消息传递给订阅了该主题的订阅者。
发布消息的具体步骤如下:
-
建立与MQTT代理的连接。
-
发布者选择一个主题。
-
发布者确定消息的质量等级。
-
发布者将消息内容和主题信息发送给MQTT代理。
-
MQTT代理负责将消息传递给订阅了该主题的订阅者。
通过发布消息,可以实现设备之间的实时通信和数据传输,使得物联网设备的集成和交互更加灵活和可靠。
1.3.4 订阅消息
在MQTT中,设备可以通过订阅主题来接收消息。订阅主题类似于消息的分类,每个主题可以有多个订阅者。当有新的消息发布到主题时,所有订阅了该主题的设备都会收到相应的消息。
设备订阅消息的过程如下:
-
设备连接到MQTT代理服务器。
-
设备发送订阅请求,指定要订阅的主题。
-
MQTT代理服务器确认订阅请求,并记录设备与主题之间的关系。
-
当有新消息发布到设备订阅的主题时,MQTT代理服务器将消息发送给所有订阅该主题的设备。
-
设备接收到消息,并进行相应的处理。
通过MQTT订阅消息,设备可以实时获取感兴趣的数据,并根据需要进行相应的操作。这种发布-订阅模式使得设备之间的通信更加灵活和高效,适用于各种物联网应用场景。
2 认识MQTT报文结构
2.1 MQTT消息体结构
MQTT发布一则消息,需要如下内容,如图二所示
功能 | 内容 | 注释 |
---|---|---|
主题(Topic) | switch | MQTT发布Message必须指定一个“主题” |
消息体(Payload) | { "switch": false } | 主题(Topic)下的消息内容 |
服务质量等级(QoS) | QoS0 | 可选择QoS0、QoS1、QoS2 |
保留标志(retained) | Disable | Broker上是否保留消息 |
图二 发布消息体内容
2.1.1 认识主题(Topic)
-
主题的一般范例
Topic就是代表某种含义的一串字符,例如: "humidity", "lux_value","relay-1"。编写Topic必须注意如下规范:
1)主题是区分大小写的
2)主题可以使用空格
3)使用英文主题
-
主题分级
MQTT协议为了更好的对主题进行管理和分类,支持主题分级,对主题进行分级处理,各个级别之间使用" / "符号 进行分隔。 举个例子:
"fac/tsb/rly/state"
在以上示例中一共有四级主题,分别是第 1 级 fac、第 2 级 tsb、第三级 rly、第 4 级 state。
-
通配符
当客户端订阅主题时,可以使用通配符同时订阅多个主题。通配符只能在订阅主题时使用,下面我们将 介绍两种通配符:单级通配符和多级通配符。
通配符 | 说明 | 范例 |
---|---|---|
+ | 单级通配符可以匹配任意一个主题级别, 注意是一个主题级别 | fac/tsb/+/state 可以匹配: fac/tsb/rly-1/state fac/tsb/rly-2/state fac/tsb/rly-3/state |
# | 多级通配符自然是可以匹配任意数量个主题级别, 而不再是单一主题级别 | fac/tsb/# 可以匹配: fac/tsb/rly-1/state fac/tsb/humidity/value fac/tsb/fun/state |
2.1.2 认识QoS(Quality of Service levels)
MQTT 设计了一套保证消息稳定传输的机制,包括消息应答、存储和重传。在这套机制下,提供了三种不同级别的 QoS(Quality of Service) ,也就是 MQTT 协议有三种服务质量等级:
QoS值 | 描述 |
---|---|
0 | MQTT 服务端和客户端不会对消息传输是否成功进行确认和检查。消息能否成功 传输全看网络环境是否稳定。 |
1 | 发送端在消息发送完成后,会检查接收端是否已经成功接收到了消息。发送端向接收端发送 PUBLISH 报文,当接收端收到 PUBLISH 报文后会向发送端回复一个 PUBACK 报 文, 如果发送端收到 PUBACK 报文,那么它就知道消息已经被接收端成功接收 |
2 | MQTT 协议可以确保接收端只接收一次消息 |
为了更好的理解 QoS,下面通过3张图来描述其工作流程:
1)QoS = 0
2)QoS = 1
3)QoS = 2
MQTT 服务质量最高级是 2 级,即 QoS=2。当 MQTT 服务质量为 2 级时, MQTT 协议可以确保接收端只接收一次消息。 为了确保接收端只接收到一次消息, PUBLISH 报文的收发过程相对更加复杂 ,其具体步骤如下:
执行Step | 完成的任务 |
---|---|
1 | publiser向subscriber发送 报文 |
2 | subscriber接收到 PUBLISH 报文后,向publiser回复一个 PUBREC 报文 |
3 | publiser收到 PUBREC 报文后,会再次向subscriber发送 PUBREL 报文 |
4 | subscriber接收到 PUBREL 报文后,会再次向publiser回复一个 PUBCOMP 报文。 如果publiser接收到 PUBCOMP 报文表示消息传输成功,它确认subscriber已经成功接收到消息 |
2.1.3 保留标志(retained)
MQTT Broker对MQTT Client发布的消息进行保留,如果有其它MQTT Client订阅了该消息对应的主题时,MQTT Broker会立即将保留消息推送给subscriber, 而不必等到publiser向主题发布新消息时subscriber才会收到消息。
现在使用以MQTT.fx作为MQTT Client, 连接EMQX ( MQTT Broker )
使能Retained后,发布一个switch消息,在EMQX 上可以看见保留消息面板存在 topic为switch的消息
2.2 MQTT心跳包
MQTT Client在没有向MQTT Broker发送消息的空闲时间里,定时向MQTT Broker发送一个心跳包, 这个心跳包被称为心跳请求,其实质就是向MQTT Broker发送一个 PINGREQ 报文;当MQTT Broker收到PINGREQ 报文后就知道该MQTT Client依然在线,然后向MQTT Client回复一个 PINGRESP 报文,称为心跳响应。
登录到EMQX服务器上,可以看见每个Client 都有心跳时间。
2.3 MQTT遗嘱机制
客户端断开与服务端的连接通常是有两种方式的:
断开方式 | 描述 |
---|---|
主动断开连接 | Client主动向Broker发送 DISCONNECT 报文,请求断开连接, |
异常断开连接 | Client意外掉线。被动与Broker断开了连接。 |
MQTT 协议允许Client在“Onlive”状态写好遗嘱,一旦Client意外断线,Broker就可以将Client的遗嘱消息广播出去。下面总结遗属Message被广播的步骤:
step - 1: Client在“Onlive”状态写好遗嘱messge
step - 2: Client意外原因断开与Broker连接
step - 3:Broker监测到Client断开连接,Broker广播遗嘱messge给subcriber
遗属Message的消息体如下:
内容 | 说明 |
---|---|
willTopic | 遗嘱主题 |
willMessage | 遗嘱消息 |
willRetain | 遗嘱消息的保留标志 |
willQoS | 遗嘱消息的 QoS |
2.4 MQTT 用户认证
MQTT Client 的用户名和密码是连接MQTT Broker的重要参数,其主要用于Broker可以方便的管理每个Client。登录EMQX服务器,可以看见,使能 password_based 功能后,所有的Client连接该Broker必须输入正确的用户名和密码才能登录。
3 体验MQTT
现在使用EMQX搭建一个MQTT Broker,并创建3个user,使用MQTT.fx连接MQTT Broker实现数据数据发布和订阅功能。
Step-1: 登录EMQX创建3个Client
Step-2:使用MQTT.fx模拟3个Client登录该MQTT Broker
Step-3:
实现功能:
mqtt_user1发布消息:
{
"switch": false
}
mqtt_user2和mqtt_ubuntu_user订阅这个消息
1) mqtt_user1发布消息
2)mqtt_user2和mqtt_ubuntu_user订阅这个消息
查看订阅消息的内容,其和mqtt_user1发送的消息一致