MQTT指南
MQTT指南 - 定义、用例、应用和资源
尽管有几种物联网通信选项,但由于它提供的优势,MQTT已成为默认的网络协议,这将在本网页中详细说明。
什么是MQTT?
MQTT是一种面向机器到机器(M2M)/物联网的通信协议,设计为一种轻量级的发布/订阅消息工具。在需要小资源占用和/或网络带宽有限的情况下,MQTT非常有用。MQTT是由IBM的Andy Stanford-Clark博士和阿伦·尼珀(Arlen Nipper)于1999年创建的。当时,IBM正在与一家石油和天然气公司合作,该公司需要从偏远地区的油管中提取数据,这需要一种新的协议来满足这些要求。结果就是MQTT。
IBM直到2010年发布了MQTT 3.1规范,允许其他人创建自己的MQTT实现。开发人员迅速意识到MQTT对物联网相关用例的价值,其采用率迅速增长,创建了大量的开源代理和客户端库。2013年,IBM将MQTT提交给OASIS以进行维护和标准化。
MQTT用例
MQTT是一种灵活的网络协议,非常适合网络可能不可靠、希望最小化带宽消耗、拥有低功耗硬件或您有众多客户端设备需要访问相同数据的实时架构的任何情况。
消费者物联网
MQTT用于许多消费者物联网设备之间的通信。这可以包括从智能家居设备到自动化事物和使您的家更高效的设备。
工业物联网
MQTT是为石油和天然气行业的工业用途而设计的,由于它相对于其他网络协议的优势,因此迅速扩展到其他领域,如制造业。MQTT通过允许公司收集更多数据并更快地对此采取行动来帮助公司提高效率。
物流
MQTT非常适合对全球范围内移动的资产进行实时监控。即使互联网连接丢失,MQTT也被设计为在连接恢复后确保数据的交付。在供应链日益复杂的世界上,MQTT正变得更加重要。
移动应用程序开发
您可能熟悉的一个使用MQTT的应用程序是Facebook Messenger。Facebook Messenger团队选择MQTT而不是HTTP,因为移动应用程序相当类似于物联网工作负载,特别是对于群聊来说,MQTT的发布/订阅架构非常自然,这使得添加成员变得容易,每个群聊都是一个客户端可以订阅的主题。
对于通用移动应用程序,MQTT是理想的,因为它允许持久连接以接收新消息,而不会消耗大量带宽或耗尽手机的电池。如果您正在构建需要频繁网络通信的任何移动应用程序,MQTT可能是一个不错的选择。
MQTT工作原理
MQTT使用发布/订阅消息模式,这意味着客户端设备连接到代理,该代理在设备之间充当中间人。连接到代理的设备可以发布将被代理转发到其他连接设备的消息。每条消息都必须有一个主题,代理只会将消息传递给明确订阅了该主题的设备。
使用MQTT,任何连接的客户端设备都可以在连接到MQTT代理后发送或接收消息。每个设备还有选择仅发布消息而无需订阅主题或仅订阅主题而从不发布任何消息的选项。
以智能家居为例,可以将房屋的每个房间指定为一个主题。对于每个设备接收和处理与其无关的消息来说,这样做没有意义且效率低下。因此,MQTT 允许开发者定义主题,使得每个设备只接收它需要的数据。
MQTT优缺点
没有网络协议是完美的,MQTT 由于定义上的原因,为了优化物联网用例,不得不做出一些权衡。在本节中,您将了解关于 MQTT 的更多细节,包括其优点和缺点,以便您确定它是否适合您的项目。
MQTT 优点
MQTT 的主要优点包括
- 效率
- 可靠性
- 灵活性
MQTT 被优化以尽可能少地使用数据和能量来发送每条消息。MQTT 可以重用连接到代理的连接来发送多条消息,这比像 HTTP 这样的协议节省了资源开销。您可以想象 HTTP 就像打电话一样,每说完一句话就挂断,然后再拨打电话继续对话,这显然没有正常电话效率高。根据谷歌进行的测试,结果是 MQTT 连接建立后,每条消息通过 MQTT 发送使用的带宽比使用 HTTP 降低了 10 倍。
MQTT 在消息大小方面也更具效率。例如,MQTT 的头部是 2 字节数据,而 HTTP 的头部至少是 16 字节用于 GET 请求,并且在使用 HTTP 时,必须为每条消息发送该头部,而 MQTT 只在创建与代理的连接时发送头部。pub/sub 架构也很高效,因为它消除了每个设备都需要定期轮询以检查新消息的需求。相反,设备等待从代理直接接收消息,这不仅确保它们能够更快地获得新消息,而且更加高效。
MQTT 由于其 pub/sub 架构,因此可靠性更高,该架构允许代理缓冲消息,并在订阅的设备再次连接时保存它们。MQTT 还为消息提供服务质量级别,以确保关键数据的传输,或者允许某些消息在不包含关键数据的情况下丢弃,以节省资源。
灵活性是 MQTT 的另一个主要优点。如上所述,用户可以根据具体情况控制消息的服务级别要求。MQTT 在消息内容方面也是数据无关的,这意味着消息负载可以包含二进制数据、ASCII 文本或其他任何数据类型。MQTT 的解耦 pub/sub 架构意味着它可以通过添加更多代理来轻松扩展,以处理更多的设备或消息频率的增加。
MQTT 缺点
MQTT 的主要缺点包括
- 延迟
- 架构复杂性
- 低功耗设备上的资源需求
- 安全性
对于需要极低延迟的使用案例,MQTT 可能存在问题,因为消息必须通过 MQTT 代理作为额外步骤传递,而不是能够直接从一台设备传输到另一台设备。
MQTT 代理的管理也可能在架构方面成为复杂性来源,因为代理是另一个需要管理和监控的服务,以确保整个系统正常工作。对于更大的工作负载,可能需要多个代理实例,这需要负载均衡以确保消息在它们之间均匀分布。
虽然 MQTT 是一种轻量级协议,但它提供的功能数量使其比某些替代方案更资源密集。通常,这不会成为问题,除非是最低功耗的硬件,但如果您正在与这种类型的硬件一起工作,这可能是一个相关因素。
安全性可以被视为MQTT的另一个通用弱点。默认情况下,MQTT不提供任何安全功能——任何形式的加密都需要使用MQTT构建在其之上的底层TCP协议来实现。虽然SSL/TLS是很好的安全选项,但这仍然是需要管理和实施以确保数据安全的东西。MQTT的最新版本MQTT v5也添加了一些额外的安全功能,稍后会进行介绍。
MQTT核心概念和功能
在本节中,您将了解如果您想使用MQTT,需要了解的一些关键概念。您还将了解MQTT提供的一些基本功能。
MQTT代理
MQTT代理通过在连接的设备之间传递消息来工作。而不是每个设备都尝试与其他设备通信,这将非常复杂且资源密集,每个设备只需要创建与代理的单个连接,就可以从任何其他设备接收数据。
MQTT代理可以处理数百万个连接的MQTT客户端,并提供本节稍后将要介绍的一些功能。代理使得这些功能成为可能,这也是为什么MQTT在物联网开发者中如此受欢迎的原因。
MQTT客户端
MQTT客户端是指运行MQTT客户端软件的任何设备,允许它连接到MQTT代理。MQTT客户端可以向代理发布消息,也可以订阅主题以接收消息。任何能够运行MQTT客户端库实现并连接到MQTT代理的设备都可以是MQTT客户端。
MQTT协议细节
MQTT的核心建立在TCP/IP网络栈之上。虽然与UDP相比,这稍微有点性能和轻量级,但TCP提供了保证交付,这对于许多物联网用例至关重要。使用TCP的另一个好处是MQTT可以使用SSL/TLS加密数据。
主题
主题是MQTT组织发送到代理的消息的关键方式。每个发送的消息都需要一个定义的主题,连接的设备可以订阅主题以在消息发送时接收消息。主题是使用正斜杠分隔的UTF-8字符串。以下是一个基本的MQTT主题示例
top/middle/bottom
这些消息可以是任何东西,但理想情况下,您将有一个基本的结构来使主题层次结构逻辑清晰,便于开发者理解,随着您的应用随着时间的推移而增长并添加更多主题。主题不需要在发布消息或客户端订阅主题之前预定义,您可以在任何时候动态添加新主题,而不必担心它。
以下是一些如果您在智能家居中做些事情可能会如何构建主题的示例。
- 地下室湿度数据 -
home/basement/mainroom/humidity
- 客厅温度数据 -
home/mainfloor/livingroom/temperature
- 卧室中特定设备的消息 -
home/mainfloor/bedroom/device
除了上述基本静态文本字符串之外,MQTT还支持使用斜杠之间使用通配符运算符的动态主题。加号仅提供单级通配符匹配。如果您想要多级通配符支持,可以使用哈希标签,主题将与哈希标签之后的所有内容匹配。例如,如果您想订阅智能家居生成的每条消息,您可以使用以下主题
home/#
这些通配符运算符非常有用,但应谨慎使用——当不需要通配符时过度使用它们将导致您的代理性能下降,因为它正在使用资源向不需要消息的设备发送消息。始终确保确定设备是否需要订阅MQTT主题——如果不订阅,您将浪费带宽和处理能力来传输客户端不需要的MQTT消息。
会话
MQTT会话被认为是客户端设备请求连接到MQTT代理器直到连接中断期间发生的一切。基于此,会话可能仅仅是初始连接请求失败,也可能是一个持续时间较长的会话,客户端在此期间发布和接收了许多消息。
会话很重要,因为它们将根据涉及消息的QoS(服务质量)级别设置关联一个状态。代理器需要能够确定某些客户端设备是否已经收到了它们需要的消息,并且在某些情况下,客户端需要响应以确认消息已送达。
消息过期
MQTT允许客户端为发布的消息设置一个过期时间间隔。间隔以秒为单位设置,并告知代理器在删除消息之前应存储多长时间。如果客户端未连接时消息过期,则客户端将无法收到该消息。
保活功能
MQTT通过设置一个确认连接的间隔来确保代理器和客户端之间建立的连接仍然存活。这被称为保活功能,频率可以通过MQTT由开发者定义。如果客户端在设定的间隔内没有向代理器发送或接收消息,代理器将ping客户端并期望得到响应。如果客户端没有响应,代理器将注册该设备为已断开连接。
保留消息
保留消息是已被标记为存储在代理器中的普通MQTT消息。通过使用保留消息,任何订阅主题的客户端都将接收到最新的保留消息,这样客户端就可以获得最新的更新,而无需等待发送消息。
服务质量
服务质量(QoS)是MQTT如何控制消息的交付保证。MQTT QoS基本上是消息发送方和接收方之间关于如何定义使消息“已交付”所需条件的协议。在MQTT的情况下,有三个服务质量级别可用
- 最多一次(0) - 最基本的QoS级别,被认为是“尽力”交付。无法保证消息会到达订阅客户端,也不会向发布设备发送确认。代理器只是确认订阅的客户端设备已连接,然后将其发送消息。
- 至少一次(1) - QoS级别1保证消息的交付,但可能导致消息被发送或甚至多次投递。如果不考虑这一点,处理同一消息的多个副本可能会导致问题。
- 至少一次(2) - QoS 2 是 MQTT 提供的最高服务质量级别。它不仅保证消息被订阅客户端接收,还确保他们只能接收一次消息。MQTT 通过要求进行四部分握手来实现,首先确认客户端已收到消息,然后使用标志再次进行请求和响应,以确保没有收到重复的消息。
在消息传递过程中,涉及将消息传递到目的地的两个部分。首先,客户端创建和发布消息,并将其发送到 MQTT 代理,然后代理需要将此消息传递给订阅的客户端。
QoS 是 MQTT 提供的最重要功能之一,因为它允许开发人员根据数据的重要性设置某些保证。这意味着即使在不可靠的网络中,MQTT 也可以保证数据的传递。同时,它为开发人员提供了灵活性;如果某些数据不重要,MQTT 可以允许这些消息丢失,并在某些情况下不浪费带宽。
遗嘱和 testament
遗嘱和 testament 是 MQTT 提供的功能,允许客户端指定在由于意外错误断开连接时发送到其他客户端设备的消息。当客户端设备连接到 MQTT 代理时,遗嘱和 testament 被发送并存储在代理上。当代理检测到客户端在没有发送用于正常断开的标准 DISCONNECT 消息的情况下断开连接时,将发送该消息。
MQTT 版本 5 功能
尽管大多数 MQTT 部署仍在使用 MQTT 3.1.1,但现在 MQTT 版本 5 已提供许多强大的新功能。大多数新项目将使用 MQTT 5,随着时间的推移,现有项目也将升级到 MQTT 版本 5。以下是 MQTT 版本 5 提供的一些最佳新功能:
- 原因代码 - MQTT 版本 5 的原因代码允许在 MQTT 代理和客户端之间发生某些事件时向 MQTT 客户端发送更多信息。例如,可以发送自定义原因代码来确认某些服务质量级别、失败的连接、不同的错误、无效的主题、速率限制等。
- 断开连接消息 - MQTT v5 允许 MQTT 代理向客户端设备发送消息,说明连接关闭的原因,以便设备可以根据断开连接的原因采取行动。
- 用户属性 - 可以将键值对集合附加到消息中,以提供额外的数据或上下文。
- 服务器重定向 - 当客户端尝试连接到代理时,它可以被重定向到不同的 MQTT 代理。此功能可用于负载均衡,通过将设备发送到新的代理,如果当前代理已超过连接的某个阈值。
- 主题别名 - 主题别名是从 MQTT-SN 中提取的功能,有助于通过将长主题名称映射到更短的替代别名来减少消息大小。
- 请求/响应模式支持 - MQTT v5 为开发者提供了模拟更传统请求/响应模式的能力,适用于比 MQTT 标准发布/订阅模型更有效的情况。对于这些情况,MQTT v5 增加了向消息添加响应主题的能力,客户端可以订阅这些主题,消息将被处理得更像标准请求/响应消息,尽管由于 MQTT 的底层 pub/sub 架构,它仍然将是异步的。这个功能仅仅是一个抽象层,以便更容易创建这些类型的请求,而无需开发者额外的工作。
- 共享订阅 - 共享订阅基本上是一种客户端负载均衡形式,客户端设备都可以订阅同一个主题,消息只会发送到单个设备,而不是发送给每个设备。
- 保留消息控制 - MQTT v5 给开发者提供了更多控制保留消息如何处理的能力,例如,如果客户端首次订阅或重新连接,它们是否应该发送到设备。
MQTT安全性
安全 是任何类型软件的挑战,但物联网应用带来了另一个级别的安全挑战。由于物联网设备在计算和内存资源方面通常有限制,开发者必须在可以使用的安全工具,如加密算法等方面做出权衡。另一个挑战是高效地处理现场设备更新。如果设备无法远程访问,软件更新将变得更加昂贵,且频率更低。
在应用层,MQTT 可以配置为要求基本的用户名和密码进行身份验证。不同的 MQTT 代理实现还可能提供额外的安全功能。由于它是基于 TCP 构建的,MQTT 还提供了使用 SSL/TLS 加密 MQTT 消息数据的传输层安全选项。在网络层,开发者还可以选择尝试物理保护硬件设备和网络组件,以及使用虚拟专用网络 (VPN) 在客户端和代理之间进行通信。
MQTT资源和工具
在本节中,您将了解更广泛的 MQTT 生态系统以及一些可供开发者在应用程序中使用 MQTT 的工具。
MQTT 代理实现
有一些开源和商业 MQTT 代理可供您开始使用 MQTT。以下是其中一些最受欢迎的选项。
Mosquitto Mosquitto 是最受欢迎的开源 MQTT 代理,由 Eclipse 基金会支持。如果您不希望依赖由提供商业替代方案的开源实现的供应商支持的代理实现,Mosquitto 可能是可用的最好的 MQTT 代理。
EMQX EMQX 是由 EMQ 公司创建的开源、云原生 MQTT 代理,EMQ 是 OASIS 的创始赞助商之一,与 IBM 合作。EMQX 是第一个完全支持 MQTT 版本 5 功能的 MQTT 代理,EMQ 声称一个 EMQX 代理集群可以处理 1 亿个订阅者。
EMQ 还提供了一些其他有用的开源工具,用于处理 MQTT,如 NanoMQ 和 Neuron,这些工具与 EMQX 一起工作,有助于连接从边缘到云的物联网设备。
HiveMQ HiveMQ 是 MQTT 生态系统中的另一个流行供应商。HiveMQ 提供了一个支持 MQTT 版本 3 和 5 的开源代理,还提供了一个托管 MQTT 代理,可用于扩展您的 MQTT 应用程序,并与 InfluxDB 集成良好。
MQTT 客户端库
有大量客户端库可供您在所选语言中使用 MQTT。大多数供应商都提供自己的实现,但最受欢迎的客户库是 Eclipse 基金会支持的 Paho MQTT 库。
MQTT 数据存储
MQTT消息通常包含时间序列数据。这些数据从大量设备中以非常快的速度流进。对于许多与物联网相关的负载,这些数据也需要在接收后尽快进行分析——对于需要近实时数据访问的监控情况,长延迟是不可接受的。像时间序列数据库如InfluxDB是为了满足这些需求而设计的,并且在写入和查询数据方面提供了许多纯性能方面的优势,同时还由于内置的许多开箱即用的功能(如降采样和常见的时间序列数据分析和预测函数)而缩短了开发时间。
MQTT Sparkplug
MQTT Sparkplug是一种规范,用于定义网络边缘网关和设备之间应如何进行更标准化的通信架构。虽然Sparkplug可以用于任何MQTT应用程序,但它针对涉及SCADA和传统工业物联网用例的系统进行了优化,并使这些系统与MQTT有更好的互操作性。MQTT Sparkplug是由Eclipse创建的,该组织还维护Paho MQTT客户端库。Sparkplug规范有三个主要组件
- MQTT主题命名空间 - 默认情况下,MQTT不强制执行任何要求的主题约定或命名空间,Sparkplug旨在创建一个更标准化的主题结构约定
- MQTT状态管理 - Sparkplug定义了多种新消息类型,可以帮助进行状态管理,如处理连接状态和处理度量数据。这些消息类型包括边缘网络MQTT节点和设备本身的连接和断开消息。还有节点与设备消息类型,以及定义消息重要性的能力。
- MQTT有效负载定义 - Sparkplug使用基于Google Protobufs的消息编码。这减少了带宽使用,并允许与其他用于工业物联网应用的协议(如Modbus)更轻松地集成。Protobufs还使创建有效负载的数据模型成为可能,以定义历史数据、文件数据、数据集、通过模板的复杂数据、度量数据的元数据以及度量别名。
Node-RED
Node-RED是一个开源的低代码框架,用于创建事件驱动的应用程序。它提供了一个可视化的构建器来集成硬件和软件组件,由IBM为物联网项目设计。Node-RED是快速创建MQTT应用程序(无论是原型设计还是生产)的绝佳选择。
MQTT常见问题解答
MQTT代表什么意思?
MQTT最初代表MQ Telemetry Transport,但MQTT不再是一个缩写,只是协议的名称。
MQTT-SN是什么?
MQTT-SN代表用于传感器网络(MQTT for Sensor Networks)。MQTT-SN设计用于在无线网络上工作,并针对通常通过无线网络通信的低功耗传感器进行了优化。MQTT-SN与标准MQTT的主要区别在于,MQTT-SN不需要TCP,可以使用Zigbee或Thread等串行通信协议。其他一些区别是,MQTT-SN使用主题ID而不是主题名称,允许使用预定义的主题,并具有用于睡眠客户端设备的保活功能。
MQTT与AMQP的比较
MQTT和AMQP都是用于在系统之间发送和接收消息的异步消息协议。它们的主要区别在于MQTT高度优化用于物联网用例,因此它是一个更小、更简单的协议。AMQP旨在覆盖更广泛的应用场景,因此具有更多的功能,但同时也更复杂,效率更低。
在功能方面,AMQP可以通过默认包含SASL等安全选项来在安全选项方面胜出,而MQTT则需要您自行添加。AMQP还提供了在保持向后兼容性的同时扩展协议的能力,而MQTT的变化则需要版本更新。AMQP提供了MQTT的pub/sub模式之外的消息模式。与MQTT相比,其主要优势在于它更轻量级,因此在电池和资源受限的硬件上表现更好。MQTT还消耗更少的带宽,并在不可靠的网络中表现更好。简而言之,MQTT和AMQP之间的主要区别在于AMQP是一个通用消息协议,而MQTT从一开始就是为了适应特定用例而设计的专用协议。您应该使用MQTT还是AMQP将取决于哪个协议符合您项目的需求。
MQTT vs RabbitMQ
RabbitMQ是一个开源的消息代理,而MQTT是一个轻量级的发布/订阅网络协议,专为物联网环境中的机器对机器通信设计。RabbitMQ最初仅设计用于与AMQP一起工作,但已通过插件添加了对MQTT以及其他协议(如STOMP和HTTP)的支持。因此,RabbitMQ可以用作通用消息代理,提供诸如故障转移和集群等出色的功能,同时使用的协议可以根据您的用例进行更改。
MQTT vs HTTP
HTTP是一种请求/响应协议,主要用于互联网应用程序。HTTP可以用于物联网用例,但并非为此而设计。在不可靠的连接下移动数据以及在物联网环境中处理大量连接的设备时,HTTP在消息大小和效率方面存在许多缺点。
MQTT vs COAP
CoAP与HTTP类似,使用请求/响应模型,并通过二进制格式使其更紧凑。MQTT使用发布/订阅模型进行通信。CoAP与MQTT之间最大的区别在于MQTT侧重于成为一个多对多的通信协议,通过代理将消息传递给许多客户端设备,而CoAP主要用于客户端到服务器的点对点通信。MQTT可以被认为是用于更多事件驱动型应用程序的,而CoAP最适合用于状态传输。
MQTT vs Zigbee
Zigbee与MQTT的主要区别在于Zigbee是一个物理数据层协议,而MQTT是一个应用层协议。Zigbee专注于设备之间实际的数据传输方式,旨在用作类似于蓝牙或WiFi的网状网络设备的更简单替代方案。在许多情况下,Zigbee用作网关协议,最终将数据转换为MQTT,以便将数据传输到云中。
MQTT vs Thread
Thread是另一种旨在用于低功耗和低延迟应用的协议,在许多情况下与Zigbee非常相似。因此,与MQTT相比Zigbee的大部分信息也适用,MQTT用于应用层通信,而Thread用于较低层次的数据传输。
MQTT over websockets
一些MQTT代理提供了对websockets的支持,这使得您可以使用JavaScript从您的网络浏览器连接到MQTT代理。
什么是OASIS?
奥赛斯(OASIS,结构化信息标准推进组织)是负责开发和维护MQTT规范以及多个其他项目的联盟。奥赛斯成立于1993年,最初是一个专注于一种名为SGML的标记语言的行业协会。随着时间的推移,奥赛斯不断扩展,现在维护着如AMQP、MQTT、SAML和Legal XML等协议。奥赛斯成员包括甲骨文、红帽、通用汽车、IBM、微软、美国律师协会等。