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的关系。
特性 | 说明 |
---|---|
低带宽、低功耗 | 消息很小,适合物联网设备(比如蓝牙门锁、智能电表) |
发布/订阅模型 | 不需要设备互相知道 IP |
支持 QoS 等级 | 保证消息“至少一次”“至多一次”甚至“正好一次” |
支持保留/遗嘱消息 | 可以通知别人“我下线了”或者“我挂了” |
支持断线重连 | 网络差也能恢复连接 |
应用场景 | 说明 |
---|---|
智能家居 | 比如智能插座、温湿度传感器 |
汽车物联网 | 车辆数据上传,远程监控 |
工业自动化 | 远程设备状态监控 |
智能门锁 | 控制开关门、上传日志等 |
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。
你必须要理解下面这几点。
在可能不稳定网络环境(家庭 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还提供了非常多实用的机制和功能。
MQTT 可以感知设备掉线,而且非常精准、轻量!有点类似于WS的连接断开而且比 WebSocket 更适合资源受限的设备场景,主要依赖两部分:心跳机制 + 遗嘱消息机制。
工作原理:
客户端连接时会告诉 Broker 一个 Keep Alive 时间间隔(比如 60 秒)
这个间隔内,客户端必须发送任意一条 MQTT 报文(哪怕是 PINGREQ 心跳包);
如果 Broker 在 1.5 倍 Keep Alive 时间 内 没收到客户端任何消息,就认定这个客户端“掉线”;
Broker 会主动断开连接。
MQTT 提供专门的心跳包叫 PINGREQ / PINGRESP
一般是客户端发送 PINGREQ,Broker 回复 PINGRESP
工作原理:
客户端在连接时就设置好遗嘱消息(指定 topic、内容、QoS);
如果客户端正常断开连接(调用 DISCONNECT),不会触发遗嘱;
如果客户端意外掉线(如断电、断网,没发 DISCONNECT,心跳失联),
Broker 会在感知到客户端掉线后,自动向预设的 topic 发布这个遗嘱消息;
订阅了该 topic 的其他客户端就能收到通知,比如 “设备123离线了”。
设备上线,连接 MQTT Broker 时可以设置一个“遗嘱消息”(Will Message):
如果我哪天突然没了,请你替我 —— 发个 offline 消息到 lock/status/LOCK123456 这个 Topic。
Broker 记住这份遗嘱了,设备继续正常通信
如果设备断电、断网、挂了
Broker 开始等……等你发心跳(KeepAlive 时间 + 容忍时间)
超时没收到,Broker 确认:设备“失联了”
此时 Broker 代表设备,替你发出遗嘱消息(offline)!
在实际业务中,我们必须确认我们下发的指令是否确认送达,或者设备上报的信息是否存储成功。MQTT也提供了这样的机制:消息送达确认(QoS)。
MQTT 提供了 3 个 QoS(消息服务质量等级),你可以根据不同消息类型选择不同的级别。
QoS 等级 | 名称 | 含义 | 是否可能重复 |
---|---|---|---|
0 | 至多一次 | 发了就不管了,不确认是否送达 | ❗可能丢失 |
1 | 至少一次 | 确保 Broker 收到,可能重复投递 | ✅可能重复 |
2 | 仅一次 | 完整的四次握手确保只投一次 | ✅不会重复但性能最低 |
要“确保一定送达” —— 那就用 QoS 1 或 2。
这里有个问题了:QoS2,需要四次握手,而HTTP还只需要3次。它是不是比HTTP还重,有没有必要用?
结论:MQTT 的 QoS2 确实比 HTTP 的三次握手“还重”,但它解决的是“应用层消息投递幂等性”,而 HTTP 的三次握手解决的是“TCP 连接可靠性”,两者完全不一样。
举个例子:
设备发一条消息:"门锁已打开"
步骤如下:
客户端 → Broker
PUBLISH(消息包,带 QoS2 标志)Broker → 客户端
PUBREC(我收到了,准备确认)客户端 → Broker
PUBREL(你确认我发的吧)Broker → 客户端
PUBCOMP(确认完成了,别再发了)
这就是所谓的 PUBLISH → PUBREC → PUBREL → PUBCOMP 四步。
场景 | 推荐 QoS 等级 | 是否能接受消息重复? | 是否能接受消息丢失? | 说明 |
---|---|---|---|---|
设备上报“门已打开” | QoS 1(至少一次) | ✅ 能接受(服务去重) | ❌ 不接受(不能丢记录) | 丢就没记录,重复最多多一条 |
设备定时上报温度、电量等状态 | QoS 0(至多一次) | ✅ 能接受 | ✅ 能接受 | 实时性优先,偶尔丢一条无影响 |
远程开锁指令(云端 → 设备) | QoS 2(仅一次) | ❌ 不能接受 | ❌ 不能接受 | 重复=二次开锁,严重问题 |
设备上线通知(状态变化) | QoS 1 | ✅ 能接受 | ❌ 不接受 | 若状态丢失,会认为设备掉线 |
️ 配置/升级命令 | QoS 2 | ❌ 不能接受 | ❌ 不能接受 | 丢了没配置,重复执行出错 |
数据采样(每秒10条) | QoS 0 | ✅ 能接受 | ✅ 能接受 | 高频无状态上报,重发浪费带宽 |
用户操作反馈(按钮点击) | QoS 1 | ✅ 能接受 | ❌ 不接受 | 丢失可能影响用户体验 |
⚠️ 告警信息上传 | QoS 1 或 2(看严重级别) | ❌ 不接受 | ❌ 不接受 | 丢失报警 = 灾难 |
MQTT 的 QoS2 就是为了解决“消息只能送达一次”这个高要求场景而设计的,它通过四次握手实现幂等性,性能较低但可靠性最高。绝大多数场景下,建议使用 QoS 1 + 后端幂等处理,关键指令用 QoS2。
为了应对“设备断网”这种常见场景,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),等设备一上线就自动推给它。
项目 | MQTT(带 QoS + 缓存) | HTTP |
---|---|---|
断网时消息能否保存? | ✅ 会缓存 | ❌ 失败直接丢 |
断网后能否补发? | ✅ 自动重发 | ❌ 你要自己记住重新发 |
是否确认送达? | ✅ 有 ACK 和 QoS | ❌ 没有(除非你设计重试) |
MQTT 作为一种为物联网量身打造的轻量级通信协议,凭借其低带宽消耗、长连接机制、灵活的消息确认等级以及断线重连能力,已经成为智能设备通信的首选。相比传统的 HTTP 通信,它不仅更实时、省电,而且在弱网和高不确定环境中依然表现稳定。对于开发者而言,深入理解 MQTT 的核心机制(如 QoS、遗嘱消息、持久会话等)能够帮助我们构建出更可靠、更高效的 IoT 应用系统。未来随着物联网设备的普及,MQTT 的应用价值将愈发凸显,是每一位从业者必须掌握的重要技术。大家有兴趣的话可以去安装EMQX什么的试一下玩一玩。