MQTT协议初探

MQTT 协议简介

概览

MQTT 是一种基于发布/订阅模式的轻量级消息传输协议,专门针对低带宽和不稳定网络环境的物联网应用而设计,可以用极少的代码为联网设备提供实时可靠的消息服务。MQTT 协议广泛应用于物联网、移动互联网、智能硬件、车联网、智慧城市、远程医疗、电力、石油与能源等领域。

MQTT 协议由 Andy Stanford-Clark (IBM)和 Arlen Nipper(Arcom,现为 Cirrus Link)于 1999 年发布。 按照 Nipper 的介绍,MQTT 必须具备以下几点:

  • 简单容易实现
  • 支持 QoS(设备网络环境复杂)
  • 轻量且省带宽(因为那时候带宽很贵)
  • 数据无关(不关心 Payload 数据格式)
  • 有持续地会话感知能力(时刻知道设备是否在线)

据 Arlen Nipper 在 [IBM Podcast 上的自述](https://f.hubspotusercontent00.net/hubfs/6941105/Que es MQTT - IBM podcast - Piper, Diaz, Nipper - 11182011-1.pdf),MQTT 原名是 MQ TT,注意 MQTT之间的空格,其全称为: MQ Telemetry Transport,是九十年代早期他在参与 Conoco Phillips 公司的一个原油管道数据采集监控系统(pipeline SCADA system)时开发的一个实时数据传输协议。它的目的在于让传感器通过带宽有限的 VSAT ,与 IBM 的 MQ Integrator 通信。由于 Nipper 是遥感和数据采集监控专业出身,所以按业内惯例取了 MQ TT 这个名字。

MQTT 与其他协议对比

MQTT vs HTTP

  • MQTT 的最小报文仅为 2 个字节,比 HTTP 占用更少的网络开销。
  • MQTT 与 HTTP 都能使用 TCP 连接,并实现稳定、可靠的网络连接。
  • MQTT 基于发布订阅模型,HTTP 基于请求响应,因此 MQTT 支持双工通信。
  • MQTT 可实时推送消息,但 HTTP 需要通过轮询获取数据更新。
  • MQTT 是有状态的,但是 HTTP 是无状态的。
  • MQTT 可从连接异常断开中恢复,HTTP 无法实现此目标。

MQTT vs XMPP

MQTT 协议设计简单轻量、路由灵活,将在移动互联网、物联网消息领域,全面取代 PC 时代的 XMPP 协议。

  • MQTT 报文体积小且编解码容易,XMPP 基于繁重的 XML,报文体积大且交互繁琐。
  • MQTT 基于发布订阅模式,相比 XMPP 基于 JID 的点对点消息路由更为灵活。
  • MQTT 支持 JSON、二进制等不同类型报文。XMPP 采用 XML 承载报文,二进制必须 Base64 编码等处理。
  • MQTT 通过 QoS 保证消息可靠传输,XMPP 主协议并未定义类似机制。

为什么 MQTT 是适用于物联网的最佳协议?

据 IoT Analytics 最新发布的《2022 年春季物联网状况》研究报告显示,到 2022 年,物联网市场预计将增长 18%,达到 144 亿活跃连接。

在如此大规模的物联网需求下,海量的设备接入和设备管理对网络带宽、通信协议以及平台服务架构都带来了巨大的挑战。对于物联网协议来说,必须针对性地解决物联网设备通信的几个关键问题:网络环境复杂而不可靠、内存和闪存容量小、处理器能力有限。

MQTT 协议正是为了应对以上问题而创建,经过多年的发展凭借其轻量高效、可靠的消息传递、海量连接支持、安全的双向通信等优点已成为物联网行业的首选协议。

MQTT 成为物联网首选协议

轻量高效,节省带宽

MQTT 将协议本身占用的额外消耗最小化,消息头部最小只需要占用 2 个字节,可稳定运行在带宽受限的网络环境下。同时,MQTT 客户端只需占用非常小的硬件资源,能运行在各种资源受限的边缘端设备上。

可靠的消息传递

MQTT 协议提供了 3 种消息服务质量等级(Quality of Service),保证了在不同的网络环境下消息传递的可靠性。

  • QoS 0:消息最多传递一次。

    如果当时客户端不可用,则会丢失该消息。发布者发送一条消息之后,就不再关心它有没有发送到对方,也不设置任何重发机制。

  • QoS 1:消息传递至少 1 次。

    包含了简单的重发机制,发布者发送消息之后等待接收者的 ACK,如果没收到 ACK 则重新发送消息。这种模式能保证消息至少能到达一次,但无法保证消息重复。

  • QoS 2:消息仅传送一次。

    设计了重发和重复消息发现机制,保证消息到达对方并且严格只到达一次。

更多关于 MQTT QoS 的介绍可查看博客:MQTT QoS 服务质量介绍

除了 QoS 之外,MQTT 还提供了清除会话(Clean Session)机制。对于那些想要在重新连接后,收到离线期间错过的消息的客户端,可在连接时设置关闭清除会话,此时服务端将会为客户端存储订阅关系及离线消息,并在客户端再次上线后发送给客户端。

海量连接支持

MQTT 协议从诞生之时便考虑到了日益增长的海量物联网设备,得益于其优秀的设计,基于 MQTT 的物联网应用及服务可轻松具备高并发、高吞吐、高可扩展能力。

连接海量的物联网设备,离不开 MQTT 服务器的支持。目前,MQTT 服务器中支持并发连接数最多的是 EMQX。最近发布的 EMQX 5.0 通过一个 23 节点的集群达成了 1 亿 MQTT 连接+每秒 100 万消息吞吐,这使得 EMQX 5.0 成为目前为止全球最具扩展性的 MQTT 服务器。

安全的双向通信

依赖于发布订阅模式,MQTT 允许在设备和云之间进行双向消息通信。发布订阅模式的优点在于:发布者与订阅者不需要建立直接连接,也不需要同时在线,而是由消息服务器负责所有消息的路由和分发工作。

安全性是所有物联网应用的基石,MQTT 支持通过 TLS/SSL 确保安全的双向通信,同时 MQTT 协议中提供的客户端 ID、用户名和密码允许我们实现应用层的身份验证和授权。

在线状态感知

为了应对网络不稳定的情况,MQTT 提供了心跳保活(Keep Alive)机制。在客户端与服务端长时间无消息交互的情况下,Keep Alive 保持连接不被断开,若一旦断开,客户端可即时感知并立即重连。

同时,MQTT 设计了遗愿(Last Will) 消息,让服务端在发现客户端异常下线的情况下,帮助客户端发布一条遗愿消息到指定的 MQTT 主题

另外,部分 MQTT 服务器如 EMQX 也提供了上下线事件通知功能,当后端服务订阅了特定主题后,即可收到所有客户端的上下线事件,这样有助于后端服务统一处理客户端的上下线事件。

MQTT 5.0 与 3.1.1

在 MQTT 3.1.1 发布并成为 OASIS 标准的四年后,MQTT 5.0 正式发布。这是一次重大的改进和升级,它的目的不仅仅是满足现阶段的行业需求,更是为行业未来的发展变化做了充足的准备。

MQTT 5.0 在 3.1.1 版本基础上增加了会话/消息延时、原因码、主题别名、用户属性、共享订阅等更加符合现代物联网应用需求的特性,提高了大型系统的性能、稳定性与可扩展性。目前,MQTT 5.0 已成为绝大多数物联网企业的首选协议,我们建议初次接触 MQTT 的开发者直接使用该版本。

如果您已经对 MQTT 5.0 产生了一些兴趣,想了解更多,您可以尝试阅读 MQTT 5.0 探索系列文章,该系列文章将以通俗易懂的方式为您介绍 MQTT 5.0 的重要特性。

协议分析

MQTT订阅与发布

​ MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。

​ MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。

提供了一对多的消息分发机制,从而实现与应用程序的解耦。

img

MQTT 服务器是发布-订阅架构的核心。目前主流的MQTT服务器有:Eclipse Mosquitto、EMQ X、HiveMQ CE、VerneMQ

​ MQTT(Message Queuing Telemetry Transport)协议中的发布者、订阅者、代理和主题是其核心概念,它们共同构建了一个灵活且可扩展的消息传递系统。

发布者(Publisher):

发布者是MQTT协议中的消息发送方。它们负责创建并发布消息到MQTT代理(Broker)。发布者将消息发送到特定的主题(Topic),而不直接发送给特定的订阅者。这使得发布者无需知道哪些订阅者正在监听其发布的消息,从而实现了发布者和订阅者之间的解耦。

订阅者(Subscriber):

订阅者是MQTT协议中的消息接收方。它们向MQTT代理订阅感兴趣的主题,并接收该主题上发布的所有消息。订阅者可以根据需要订阅多个主题,以便接收来自不同源的消息。一旦订阅者接收到消息,它们可以根据自己的业务逻辑对消息进行处理。

代理(Broker):

MQTT代理是MQTT协议中的核心组件,负责在发布者和订阅者之间传递消息。代理接收发布者发送的消息,并根据订阅者的订阅信息将消息转发给相应的订阅者。代理还负责管理订阅关系,确保消息能够准确地发送给需要的订阅者。此外,代理还可以提供持久化存储功能,以便在订阅者离线时保存消息,并在订阅者重新上线时发送这些消息。

主题(Topic):

主题是MQTT协议中用于对消息进行分类的关键概念。它是一个UTF-8编码的字符串,可以包含多个层级关系(通过斜杠/表示)。发布者将消息发布到特定的主题,而订阅者则订阅感兴趣的主题以接收消息。主题的设计使得MQTT协议能够支持灵活的消息传递模式,允许不同的设备和应用程序通过共享的主题进行通信。

img

QoS(Quality of Service levels)

MQTT 协议中规定了消息服务质量(Quality of Service),它保证了在不同的网络环境下消息传递的可靠性,QoS 的设计是 MQTT 协议里的重点。

QoS 0 最多分发一次

这一级别会发生消息丢失或重复,消息发布依赖于底层TCP/IP网络。即:<=1
img

QoS 1 至少分发一次

QoS 1 承诺消息将至少传送一次给订阅者。

img

QoS 2 只分发一次

使用 QoS 2,我们保证消息仅传送到目的地一次。为此,带有唯一消息 ID 的消息会存储两次,首先来自发送者,然后是接收者。QoS 级别 2 在网络中具有最高的开销,因为在发送方和接收方之间需要两个流。

img

如何决定QoS?

MQTT 发布消息 QoS 保证不是端到端的,是客户端与服务器之间的。订阅者收到 MQTT 消息的 QoS 级别,最终取决于发布消息的 QoS 和主题订阅的 QoS。

MQTT 数据包结构

img

固定报头(Fixed header),存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识。

可变报头(Variable header),存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容。

有效载荷(Payload),存在于部分MQTT数据包中,表示客户端收到的具体内容。

整体MQTT的消息格式如下图所示;

img

MQTT固定头

每个MQTT控制包都包含一个固定报头

消息类型

img

标识位(bit0~3)
img

DUP1: 控制报文的重复分发标志

QoS2:PUBLISH报文的服务质量等级

RETAIN3: PUBLISH报文的保留标志

剩余长度

剩余长度是一个可变字节整数,表示当前控制报文中剩余的字节数,包括可变报头和有效载荷中的数据。

可变报头

可变报头位于固定报头和有效载荷之间,可变报头的内容根据报文类型的不同而不同。通常都包括一个2字节的数据包标识字段,这些类型的包有:PUBLISH (QoS > 0)、PUBACK、PUBREC、PUBREL、PUBCOMP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK

有效载荷

Payload有效载荷位于MQTT数据包的第三部分,CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型包含有效载荷。

CONNECT有效载荷内容主要是:客户端的ClientID、遗嘱主题、遗嘱Message以及用户名和密码。

SUBSCRIBE有效载荷内容是主题过滤器指明需要订阅的Topic以及QoS。

SUBACK有效载荷内容包含一个返回码清单,每个返回码对应等待确认的SUBSCRIBE报文中的一个主题过滤器。UNSUBSCRIBE有效载荷内容是客户端想要取消订阅的主题过滤器。

参考

https://blog.csdn.net/qq_33642970/article/details/136707440

https://www.emqx.com/zh/blog/what-is-the-mqtt-protocol