MQTT 是什么?一文读懂 MQTT 协议的原理与优势

1,MQTT 是什么

MQTT(Message Queuing Telemetry Transport) 是一种发布/订阅消息协议,最早由 IBM 提出,用于低功耗、低带宽场景下的数据传输,尤其适用于物联网(IoT)设备通信。

  • 全称:Message Queuing Telemetry Transport

  • 角色:定义“设备如何发送/接收消息”的规则(通信协议)

  • 关键机制发布 / 订阅 模型(Publish / Subscribe)

不是软件、平台、工具本身,而是一套规则,就像交通规则一样,谁都能实现它。它可以让不同设备之间通过“发布/订阅”的方式进行通信的一种协议,尤其适合网络不好、带宽低、设备资源少的场景。

名称 全称 角色 类比
MQTT Message Queuing Telemetry Transport 一种协议(通信规则) 寄快递的规则,寄件人、寄给谁、格式等规定
MQTT实现者 如:EMQX、Mosquitto、HiveMQ等 MQTT协议的具体产品 快递公司,比如顺丰、圆通、韵达等

就类似于AMQP和RabbitMQ的关系。

2,MQTT 的优势

特性 说明
低带宽、低功耗 消息很小,适合物联网设备(比如蓝牙门锁、智能电表)
发布/订阅模型 不需要设备互相知道 IP
支持 QoS 等级 保证消息“至少一次”“至多一次”甚至“正好一次”
支持保留/遗嘱消息 可以通知别人“我下线了”或者“我挂了”
支持断线重连 网络差也能恢复连接

3,MQTT 应用场景

应用场景 说明
智能家居 比如智能插座、温湿度传感器
汽车物联网 车辆数据上传,远程监控
工业自动化 远程设备状态监控
智能门锁 控制开关门、上传日志等

4,MQTT 与 MQ 的关系与异同

MQTT和MQ是两个非常容易被混淆的问题。

MQTT 常用于 IoT 场景,而 MQ 通常是指实现了各种消息传输协议的中间件产品,如 RabbitMQ、Kafka 等。两者都基于生产者-消费者-Broker 架构,但 MQTT 是协议层,MQ 是产品层。

区别对比表

对比维度 MQTT MQ
本质 协议 架构/中间件产品
设计目标 轻量、低带宽、低功耗、实时 解耦服务、异步处理、高吞吐
模式 发布/订阅(Pub/Sub) 多种:点对点、发布订阅、事务型等
使用者 通常用于 物联网设备 通信 通常用于 后端服务之间通信
常见产品 EMQX、Mosquitto、HiveMQ RabbitMQ、Kafka、RocketMQ、ActiveMQ
消息确认 有 QoS(0, 1, 2)级别控制 更强的持久化、事务等保障
协议层 应用层协议(TCP/IP之上) 实现通信机制的一种手段(不局限于协议)
适合场景 智能家居、远程遥测 电商下单、日志收集、订单系统异步解耦

比如现在有个智能门锁,它会在我开门的时候,记录下是指纹开门、人脸开门等。就是通过MQTT传递到后端,然后后端将这些动作记录到数据库,此时呢可以采用MQ进行异步处理。

HTTP 和 MQTT 是不是都能干这事?确实都可以。那么很多人就会有一个疑问,为什么不直接使用http。

5,为什么物联网领域强烈推荐 MQTT 而不用HTTP

你必须要理解下面这几点。

在可能不稳定网络环境(家庭 Wi-Fi 信号边缘、蜂窝网络) 的物联网设备,MQTT 的设计优势是碾压性的。“专为物联网和资源受限环境设计”,意味着 MQTT 在 网络不好、设备性能差、电量有限、通信频繁但数据量小的环境下,表现比 HTTP 更加稳定、节能、实时、可靠

场景:一个低功耗蓝牙门锁,开锁上传一条记录。

维度 HTTP MQTT 说明
连接方式 每次都要重新建立连接(TCP + TLS + 传头部) 长连接(TCP 只建立一次) MQTT 建立连接后,可以一直保持(心跳维持)
数据体积 较大(有大量 header) 极小(只有必要数据) MQTT header 只占 2 字节起
实时性 发了就断(非实时) 实时推送,毫秒级 适合做“开锁指令下发”
功耗 连接 + 断开消耗高 一直连接,省电 特别重要!门锁是电池供电
网络要求 网络波动时易失败 支持断线重连、QoS MQTT 可以断线缓存、自动重发
传输方向 客户端只能请求服务器 服务端也可以主动下发指令 HTTP 无法推送(除 WebSocket)
协议层 应用层 HTTP 应用层 MQTT(基于 TCP) MQTT 比 HTTP 更轻

HTTP 像是打一次电话就挂断,MQTT 像是一直保持在线的对讲机,适合设备随时上下线、随时传消息的环境。

作为IoT设备通信间的最佳协议之一,MQTT还提供了非常多实用的机制和功能。

6,掉线感知

MQTT 可以感知设备掉线,而且非常精准、轻量!有点类似于WS的连接断开而且比 WebSocket 更适合资源受限的设备场景,主要依赖两部分:心跳机制 + 遗嘱消息机制

6.1 心跳机制(Keep Alive)

工作原理:

  1. 客户端连接时会告诉 Broker 一个 Keep Alive 时间间隔(比如 60 秒)

  2. 这个间隔内,客户端必须发送任意一条 MQTT 报文(哪怕是 PINGREQ 心跳包);

  3. 如果 Broker 在 1.5 倍 Keep Alive 时间 内 没收到客户端任何消息,就认定这个客户端“掉线”;

  4. Broker 会主动断开连接。

心跳包说明:
  • MQTT 提供专门的心跳包叫 PINGREQ / PINGRESP

  • 一般是客户端发送 PINGREQ,Broker 回复 PINGRESP

6.2 遗嘱消息(Last Will and Testament)

工作原理:

  1. 客户端在连接时就设置好遗嘱消息(指定 topic、内容、QoS);

  2. 如果客户端正常断开连接(调用 DISCONNECT),不会触发遗嘱;

  3. 如果客户端意外掉线(如断电、断网,没发 DISCONNECT,心跳失联),

    • Broker 会在感知到客户端掉线后,自动向预设的 topic 发布这个遗嘱消息

    • 订阅了该 topic 的其他客户端就能收到通知,比如 “设备123离线了”。

6.3 模拟一下连接流程:

  1. 设备上线,连接 MQTT Broker 时可以设置一个“遗嘱消息”(Will Message):

    如果我哪天突然没了,请你替我 —— 发个 offline 消息到 lock/status/LOCK123456 这个 Topic。

  2. Broker 记住这份遗嘱了,设备继续正常通信

如果设备断电、断网、挂了

  1. Broker 开始等……等你发心跳(KeepAlive 时间 + 容忍时间)

  2. 超时没收到,Broker 确认:设备“失联了”

  3. 此时 Broker 代表设备,替你发出遗嘱消息(offline)!

7,送达确认机制(QoS 质量等级)

在实际业务中,我们必须确认我们下发的指令是否确认送达,或者设备上报的信息是否存储成功。MQTT也提供了这样的机制:消息送达确认(QoS)

MQTT 提供了 3 个 QoS(消息服务质量等级),你可以根据不同消息类型选择不同的级别。

QoS 等级 名称 含义 是否可能重复
0 至多一次 发了就不管了,不确认是否送达 ❗可能丢失
1 至少一次 确保 Broker 收到,可能重复投递 ✅可能重复
2 仅一次 完整的四次握手确保只投一次 ✅不会重复但性能最低

要“确保一定送达” —— 那就用 QoS 1 或 2。

这里有个问题了:QoS2,需要四次握手,而HTTP还只需要3次。它是不是比HTTP还重,有没有必要用?

结论:MQTT 的 QoS2 确实比 HTTP 的三次握手“还重”,但它解决的是“应用层消息投递幂等性”,而 HTTP 的三次握手解决的是“TCP 连接可靠性”,两者完全不一样。

7.1 MQTT QoS2 的四次握手详细流程

举个例子:

设备发一条消息:"门锁已打开"

步骤如下:

客户端 → Broker
    PUBLISH(消息包,带 QoS2 标志)

Broker → 客户端
    PUBREC(我收到了,准备确认)

客户端 → Broker
    PUBREL(你确认我发的吧)

Broker → 客户端
    PUBCOMP(确认完成了,别再发了)

这就是所谓的 PUBLISH → PUBREC → PUBREL → PUBCOMP 四步。

7.2 常见场景下该选哪种 QoS?

场景 推荐 QoS 等级 是否能接受消息重复? 是否能接受消息丢失? 说明
设备上报“门已打开” QoS 1(至少一次) ✅ 能接受(服务去重) ❌ 不接受(不能丢记录) 丢就没记录,重复最多多一条
设备定时上报温度、电量等状态 QoS 0(至多一次) ✅ 能接受 ✅ 能接受 实时性优先,偶尔丢一条无影响
远程开锁指令(云端 → 设备) QoS 2(仅一次) ❌ 不能接受 ❌ 不能接受 重复=二次开锁,严重问题
设备上线通知(状态变化) QoS 1 ✅ 能接受 ❌ 不接受 若状态丢失,会认为设备掉线
️ 配置/升级命令 QoS 2 ❌ 不能接受 ❌ 不能接受 丢了没配置,重复执行出错
数据采样(每秒10条) QoS 0 ✅ 能接受 ✅ 能接受 高频无状态上报,重发浪费带宽
用户操作反馈(按钮点击) QoS 1 ✅ 能接受 ❌ 不接受 丢失可能影响用户体验
⚠️ 告警信息上传 QoS 1 或 2(看严重级别) ❌ 不接受 ❌ 不接受 丢失报警 = 灾难

7.3 总结:

MQTT 的 QoS2 就是为了解决“消息只能送达一次”这个高要求场景而设计的,它通过四次握手实现幂等性,性能较低但可靠性最高绝大多数场景下,建议使用 QoS 1 + 后端幂等处理,关键指令用 QoS2。

8,断网期间消息缓存(Session + 离线队列)

为了应对“设备断网”这种常见场景,MQTT 还提供了“持久会话”和“离线消息缓存+补发”机制,只要你用对了配置,这些能力就自动为你工作,不需要手动管太多逻辑。

场景一:设备是发布者

比如:设备 ➜ 上报开锁事件 lock/event/open

// 1. 保持会话
options.setCleanSession(false);

// 2. 设置消息QoS
message.setQos(1);

这样配置的作用是:

如果设备临时断网(比如掉线3秒),MQTT SDK 会自动把这段时间要发的消息缓存起来,等网络恢复后补发出去,你无需自己管理“重发队列”。

场景二:设备是订阅者(用于接收服务端下发命令)

比如:平台 ➜ 给设备下发 “关锁指令” 到 lock/cmd/close

设备代码这样写:

options.setCleanSession(false); // 保持会话
client.subscribe("lock/cmd/close", 1); // 订阅指令主题,QoS=1

这时 cleanSession=false 的意义是:

如果设备断网,MQTT Broker 会保存这段时间发给它的消息(只要 QoS > 0),等设备一上线就自动推给它。

再对比 HTTP :

项目 MQTT(带 QoS + 缓存) HTTP
断网时消息能否保存? ✅ 会缓存 ❌ 失败直接丢
断网后能否补发? ✅ 自动重发 ❌ 你要自己记住重新发
是否确认送达? ✅ 有 ACK 和 QoS ❌ 没有(除非你设计重试)

总结

MQTT 作为一种为物联网量身打造的轻量级通信协议,凭借其低带宽消耗、长连接机制、灵活的消息确认等级以及断线重连能力,已经成为智能设备通信的首选。相比传统的 HTTP 通信,它不仅更实时、省电,而且在弱网和高不确定环境中依然表现稳定。对于开发者而言,深入理解 MQTT 的核心机制(如 QoS、遗嘱消息、持久会话等)能够帮助我们构建出更可靠、更高效的 IoT 应用系统。未来随着物联网设备的普及,MQTT 的应用价值将愈发凸显,是每一位从业者必须掌握的重要技术。大家有兴趣的话可以去安装EMQX什么的试一下玩一玩。

你可能感兴趣的:(网络,物联网)