MQTT(Message Queuing Telemetry Transport)是一种轻量级、基于发布-订阅模式的消息传输协议,适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它在物联网应用中广受欢迎,能够实现传感器、执行器和其它设备之间的高效通信。
要了解 MQTT 的工作原理,首先需要掌握以下几个概念:MQTT 客户端、MQTT Broker、发布-订阅模式、主题、QoS。
任何运行 MQTT 客户端库的应用或设备都是 MQTT 客户端。例如,使用 MQTT 的即时通讯应用是客户端,使用 MQTT 上报数据的各种传感器是客户端,各种 MQTT 测试工具也是客户端。
MQTT Broker 是负责处理客户端请求的关键组件,包括建立连接、断开连接、订阅和取消订阅等操作,同时还负责消息的转发。一个高效强大的 MQTT Broker 能够轻松应对海量连接和百万级消息吞吐量,从而帮助物联网服务提供商专注于业务发展,快速构建可靠的 MQTT 应用。
发布-订阅模式与客户端-服务器模式的不同之处在于,它将发送消息的客户端(发布者)和接收消息的客户端(订阅者)进行了解耦。发布者和订阅者之间无需建立直接连接,而是通过 MQTT Broker 来负责消息的路由和分发。
下图展示了 MQTT 发布/订阅过程。温度传感器作为客户端连接到 MQTT Broker,并通过发布操作将温度数据发布到一个特定主题(例如 Temperature)。MQTT Broker 接收到该消息后会负责将其转发给订阅了相应主题(Temperature)的订阅者客户端。
MQTT 协议根据主题来转发消息。主题通过 / 来区分层级,类似于 URL 路径,例如:
chat/room/1
sensor/10/temperature
sensor/+/temperature
MQTT 主题支持以下两种通配符:+ 和 #。
注意:通配符主题只能用于订阅,不能用于发布。
MQTT 提供了三种服务质量(QoS),在不同网络环境下保证消息的可靠性。
在了解了 MQTT 的基本组件之后,让我们来看看它的一般工作流程:
下面我们将通过一些简单的示例来展示如何使用 MQTT。在开始之前,需要准备 MQTT Broker 和 MQTT 客户端。
您可以选择私有部署或完全托管的云服务来建立自己的 MQTT Broker。或者您也可以使用免费的公共 Broker。
docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx
Server: broker.emqx.io
TCP Port: 1883
WebSocket Port: 8083
SSL/TLS Port: 8883
Secure WebSocket Port: 8084
在本文中,我们将使用 MQTTX 提供的支持浏览器访问的 MQTT 客户端工具,访问地址为 http://www.emqx.io/online-mqtt-client 。 MQTTX 还提供了桌面客户端和命令行工具。
MQTTX 是一款跨平台的 MQTT 5.0 桌面客户端,可在 macOS、Linux、Windows 操作系统上运行。其用户友好的聊天式界面使用户能够轻松创建多个 MQTT/MQTTS 连接,并进行 MQTT 消息的订阅和发布。
目前,各种编程语言都拥有成熟的开源 MQTT 客户端库。我们在流行的 MQTT 客户端库和 SDK 中精选了多个编程语言的 MQTT 客户端库,并提供了详细的代码示例,旨在帮助您快速了解 MQTT 客户端的使用。
在使用 MQTT 协议进行通信之前,客户端需要创建一个 MQTT 连接来连接到 Broker。
在浏览器中打开 http://www.emqx.io/online-mqtt-client , 点击页面中间的 New Connection
按钮,将看到如下页面。
我们在 Name 中输入 Simple Demo,然后点击右上角的 Connect 按钮,建立一个 MQTT 连接。如下图所示,表示连接成功。
接下来,我们在上面创建的 Simple Demo
连接中通过通配符订阅主题 sensor/+/temperature
,这样就可以接收所有传感器发送的温度数据了。
如下图所示,点击 New Subscription
按钮,在弹出框中的 Topic
字段中输入主题 sensor/+/temperature
,QoS 保持默认值 0。
订阅成功后,会在订阅列表的中间看到新增了一条记录。
接下来,我们点击左侧菜单上的 +
按钮创建两个连接,分别命名为 Sensor 1
和 Sensor 2
,用来模拟两个温度传感器。
连接创建成功后,会看到三个连接,每个连接左侧的在线状态指示灯都是绿色的。
选择 Sensor 1
连接,在页面下方的发布主题中输入 sensor/1/temperature
,在消息框中输入以下 JSON 格式的消息,然后点击右下方的发布按钮发送消息。
{
"msg": "17.2"
}
如下图所示,消息发送成功。
使用相同的步骤,在 Sensor 2
连接中发布以下 JSON 消息到 sensor/2/temperature
主题。
{
"msg": "18.2"
}
您会看到 Simple Demo 连接收到两条新消息。
点击 Simple Demo 连接,会看到两个传感器发送的两条消息。
当 MQTT 客户端向服务器发布消息时,可以设置保留消息标志。保留消息存储在消息服务器上,后续订阅该主题的客户端仍然可以收到该消息。
如下图所示,我们在 Sensor 1
连接中勾选 Retain
选项,然后向 retained_message
主题发送两条消息。
接着,我们在 Simple Demo
连接中订阅 retained_message
主题。订阅成功后,会收到 Sensor 1
发送的第二条保留消息,这说明服务器只会为主题保留最近的一条保留消息。
MQTT 客户端通常只能在在线状态下接收其它客户端发布的消息。如果客户端离线后重新上线,它将无法收到离线期间的消息。
但是,如果客户端连接时设置 Clean Session 为 false,并且使用相同的客户端 ID 再次上线,那么消息服务器将为客户端缓存一定数量的离线消息,并在它重新上线时发送给它。
本次演示使用的公共 MQTT 服务器设置为缓存 5 分钟的离线消息,最大消息数为 1000 条,且不保存 QoS 0 消息。
下面,我们创建一个 MQTT 3.1.1 连接,并用 QoS 1 来演示 Clean Session 的使用。
MQTT 5.0 中将 Clean Session 拆分成了 Clean Start 与 Session Expiry Interval。
创建一个名为 MQTT V3
的连接,设置 Clean Session 为 false,选择 MQTT 版本为 3.1.1。
连接成功后,订阅 clean_session_false
主题,并将 QoS 设置为 1。
订阅成功后,点击右上角的断开按钮,断开连接。
然后,创建一个名为 MQTT_V3_Publish
的连接,MQTT 版本也设置为 3.1.1。连接成功后,向 clean_session_false
主题发布三条消息。
接着,选择 MQTT_V3
连接,点击连接按钮重新连接到服务器,会收到三条离线消息。
MQTT 客户端在向服务器发起 CONNECT 请求时,可以选择是否发送遗嘱消息标志,并指定遗嘱消息的主题和有效载荷。
如果 MQTT 客户端异常离线(在断开连接前没有向服务器发送 DISCONNECT 消息),MQTT 服务器会发布遗嘱消息。
我们创建一个名为 Last Will
的连接来演示这个功能。为了快速看到效果,我们把 Keep Alive 设置为 5 秒。
last_will
。1
。true
。offline
。连接成功后,我们断开电脑网络超过 5 秒(模拟客户端异常断开连接),然后再恢复网络。
接着启动 Simple Demo 连接,并订阅 last_will
主题。您会收到 Last Will 连接设置的遗嘱消息。