AI摘要
MQTT是物联网事实标准,基于发布/订阅模型,通过Broker解耦,报文仅2字节。支持QoS三级、遗嘱消息与保留消息,专为低功耗弱网设计。5.0版增加原因码、共享订阅等。较HTTP更省电、支持实时推送。
如果做过物联网项目,大概率绕不开一个词:MQTT。从家里的智能灯泡到田间的土壤传感器,从产线上的机床到路边的共享单车,数十亿台设备正靠这个诞生于 1999 年的协议彼此通信。它凭什么成了物联网的事实标准?和 HTTP 比到底强在哪?这篇文章会从发布/订阅模型讲到 QoS 三级、遗嘱消息、MQTT 5.0 新特性,再配上协议对比和一段能直接跑的 Python 代码,帮你一次性把 MQTT 捋清楚。
一、从一个智能大棚说起:为什么物联网不能只用 HTTP
想象一个典型的智能农业大棚:几百个温湿度、光照、土壤墒情传感器散落田间,靠电池和太阳能板供电,通过时好时坏的 4G 网络把数据上报到云端;云端则要根据实时数据,远程控制卷帘、风机和灌溉阀门。
方案评审时,开发团队的第一反应往往是:"用 HTTP 呗,POST 一下不就完了。"思路没错,但到了弱网环境、设备成百上千、还要 7×24 小时在线的真实场景里,HTTP 的短板会全部暴露:
- 云端没法主动推。HTTP 是请求/响应模式,云端想下发一条"开风机降温"的指令,只能等设备下次轮询。轮询间隔长了,指令延迟感人;间隔短了,几千台设备一起轮询,服务器和网络直接被无谓的请求打满。
- 头部开销太大。一次 HTTP 请求光头部就可能几百字节,而设备真正要传的数据可能只有十几个字节——比如一个温度值"26.5",好比用快递大纸箱寄一张纸条。
- 功耗顶不住。每次通信都要完整的 TCP + TLS 握手,对电池供电的传感器来说,射频模块多工作一秒都是在烧钱。
这不只是农业场景的麻烦,更是整个物联网行业的共性问题:海量设备、弱网环境、低功耗约束、双向实时通信。HTTP 是为人浏览网页设计的,不是为机器之间唠嗑设计的。而 MQTT,恰恰为此而生。
二、MQTT 是什么:一个为"省钱"而生的协议
MQTT 最早是 Message Queuing Telemetry Transport(消息队列遥测传输)的缩写。不过如今官方已不再把它当缩写解释——协议内部其实没有传统意义上的消息队列,这个名字更多是历史遗留。
它的出身很能说明问题。1999 年,IBM 的 Andy Stanford-Clark 和 Arcom 公司的 Arlen Nipper 设计了这个协议,当时的场景是:通过卫星链路监控横跨荒原的石油管道。卫星通信按流量计费、带宽极窄、延迟高,沿线监测设备又靠电池供电。于是设计目标非常朴素:报文要小、协议要省电、网络断了也得扛得住。
这三个朴素目标,塑造了 MQTT 延续至今的基因:
- 报文极小:固定报头最小只有 2 个字节,对比 HTTP 动辄几百字节的文本头部,省到了极致。
- 轻量:跑在 TCP 之上(默认端口 1883,TLS 加密为 8883),单片机几十 KB 内存就能跑一个 MQTT 客户端。
- 为不稳定网络设计:内置心跳、遗嘱、分级 QoS 等一整套"断线自保"机制。
2013 年前后 IBM 将 MQTT 提交给 OASIS 标准组织,2014 年 MQTT 3.1.1 成为 OASIS 正式标准,后来被接纳为 ISO 国际标准(ISO/IEC 20922)。目前主流版本是 MQTT 3.1.1 和 MQTT 5.0(2019 年发布),5.0 是现在的推荐版本,后文会专门聊它。
eeClub-电子工程师社区:https://bbs.eeclub.top/
电子/单片机技术交流QQ群: 2169025065
三、核心架构:不是"打电话",而是"订报纸"
理解 MQTT,最关键的是理解它的通信模型——发布/订阅模式(Publish/Subscribe)。
HTTP 的请求/响应模式像打电话:你拨通对方号码直接对话,双方必须同时在线,且互相知道对方的"号码"。
发布/订阅模式则像订报纸:报社(发布者)印好报纸送到邮局(Broker),你(订阅者)提前在邮局登记"我订了科技版",每天报纸一到,邮局就按登记名单投递。报社不知道读者是谁,读者也不需要知道报社的电话——双方彻底解耦,邮局是唯一的枢纽。
在这个模型里有三个核心角色:
- Publisher(发布者):产生消息的设备或程序,比如上报温度的传感器。
- Broker(代理服务器):整个系统的"邮局",负责接收消息、按主题分发给所有订阅者,还管着连接、会话、保留消息等杂务,是唯一需要公网可达的角色。
- Subscriber(订阅者):关心某类消息的设备或程序,比如手机 App、数据大盘。
需要说明的是,发布者和订阅者只是逻辑角色,同一台设备完全可以身兼两职——摄像头既向云端发布告警,也订阅云端下发的控制指令。另外,由于设备只需主动向外连接 Broker,自己不需要公网 IP、不需要开放任何端口,天然绕开了 NAT 和防火墙的麻烦。这也是 MQTT 比"设备开端口等连接"之类方案更受欢迎的重要原因。
Topic:邮局里的"信箱编号"
消息靠什么分发?靠 Topic(主题)。Topic 是一个 UTF-8 字符串,用 / 分层,看起来像文件路径:
home/livingroom/temperature
home/livingroom/humidity
home/bedroom/temperature订阅时可以使用两种通配符:
+单层通配符:匹配恰好一层。比如home/+/temperature能同时收到客厅和卧室的温度。#多层通配符:匹配其后的任意多层,只能放在末尾。比如home/#能收到 home 下的所有消息。
四、关键特性逐个讲透
MQTT 能在弱网环境里立住脚,靠的是一组设计精巧的机制。下面几个特性是面试和实战中最高频的考点。
1. QoS:消息投递的三种"快递服务"
MQTT 把消息投递质量(Quality of Service)分成三级,可以理解为三种快递:
- QoS 0 —— 最多一次(At most once):相当于平邮,发出去就不管了,不确认、不重发。可能丢,但绝不重复。适合高频、丢了也无所谓的数据,比如每秒上报一次的实时值——丢了这帧,下秒还有新的。
- QoS 1 —— 至少一次(At least once):相当于挂号信。接收方必须回 PUBACK 确认,发送方收不到就重发。保证到达,但可能重复——确认包在路上丢了,发送方会再寄一封。适合告警、状态变更这类"宁可重复也不能丢"的消息,接收方要做幂等处理。
- QoS 2 —— 恰好一次(Exactly once):相当于双方签收的专人快递。通过 PUBREC、PUBREL、PUBCOMP 四次握手保证不重不丢,代价是开销最大、速度最慢。适合计费等"多扣一块钱都是事故"的场景。
规律很简单:QoS 越高,可靠性越强,开销和延迟也越大,工程上默认选 QoS 1 往往是最划算的折中。
还有一个容易忽略的细节:QoS 是发布端和订阅端各自声明的,Broker 实际投递时取两者的较低值——发布方用 QoS 2、而订阅方只订了 QoS 0,消息最终就按 QoS 0 投递。所以排查"为什么我的高 QoS 消息丢了"这类问题时,记得两端都查。
2. 保留消息(Retained):贴在信箱上的便签
普通消息"阅后即焚"——订阅者不在线,消息发完就没了。但发布时设置 Retain 标志后,Broker 会为这个 Topic 保存最后一条保留消息,之后任何新订阅者一订阅该主题,立刻就能收到它。
典型用法:设备上线后把自己的状态(如"online"、当前开关状态)以 Retained 方式发布。这样无论 App 什么时候打开,都能马上看到设备最新状态,而不必苦等设备下一次上报。注意保留消息每个主题只存一条,新的会覆盖旧的;想清除某个主题的保留消息,向该主题发布一条空载荷的 Retained 消息即可。
3. 遗嘱消息(LWT):设备留下的"遗言"
Last Will and Testament(遗嘱消息)是 MQTT 里最有人情味的设计。客户端连接 Broker 时可以提前登记:"如果我死得不明不白(异常掉线),请替我把这条消息发出去。"
比如摄像头连接时登记遗嘱 camera/01/status = "offline"(Retained)。一旦设备断电、断网导致连接异常断开,Broker 就会代它发布遗嘱,所有订阅者立刻知道"这台设备挂了"。配合 Retained,后打开 App 的用户也能看到离线状态。
4. Keep Alive:心跳,确认彼此还活着
TCP 感知对端"假死"很慢,MQTT 在应用层加了心跳:客户端连接时约定 Keep Alive 间隔(比如 60 秒),空闲时就发一个极小的 PINGREQ 报文,Broker 回 PINGRESP。如果 Broker 在 1.5 倍 Keep Alive 时间内没收到客户端任何消息,就判定其死亡、断开连接,并触发遗嘱消息。
5. Clean Session:断线重连后,还记得我吗
客户端通过 Clean Session 标志告诉 Broker 要不要保留会话。设为 0(持久会话)时,Broker 会记住这个客户端的订阅关系,以及它离线期间错过的 QoS 1/2 消息,等它重连后补发;设为 1 则重连后一切从零开始。
MQTT 5.0 把这个机制拆成了 Clean Start(是否全新开始)和 Session Expiry Interval(会话过期时间),表达更精确——比如让会话保留 24 小时,而不是简单的"永存/不存"。
6. 报文结构:2 字节起步的极致压缩
MQTT 报文由固定报头 + 可变报头 + 有效载荷三部分组成。固定报头第一个字节的高 4 位是报文类型(CONNECT、PUBLISH、SUBSCRIBE、PINGREQ 等共 14 种),低 4 位是标志位;之后是变长编码的"剩余长度"字段,最小只占 1 字节。也就是说,一个心跳包总共就 2 个字节——这就是 MQTT"轻"的底气。
五、MQTT 5.0:一次诚意满满的升级
2019 年发布的 MQTT 5.0 在保持轻量的前提下补齐了很多工程短板:
- 原因码(Reason Code):几乎所有响应报文都带上了标准化的原因码,连接被拒、订阅失败不再是模糊的"失败",而是明确告诉你为什么。
- 属性系统(Properties):报文可以携带灵活的元数据键值对,大量新能力都建立在这套机制上。
- 共享订阅(Shared Subscription):多个订阅者组成消费组(如
$share/group1/topic),同一条消息只投递给组内一人,天然实现负载均衡——这是 3.1.1 时代要绕很多弯才能做的事。 - 消息过期(Message Expiry Interval):发布时给消息设有效期,过期的离线消息不再补发,避免设备上线时被一堆过时指令轰炸。
- 其他改进:主题别名(用短编号替代长主题名省流量)、Receive Maximum 流量控制、服务端主动断开通知、基于 Response Topic 的请求-响应模式支持等。
一句话总结:3.1.1 够用,5.0 好用,新项目建议直接上 5.0。
六、横向对比:MQTT vs HTTP vs CoAP vs WebSocket
光说 MQTT 好还不够,放到协议堆里比一比,定位就清晰了:
| 维度 | MQTT | HTTP | CoAP | WebSocket |
|---|---|---|---|---|
| 通信模型 | 发布/订阅 | 请求/响应 | 请求/响应(类 REST) | 全双工数据流 |
| 传输层 | TCP | TCP | UDP | TCP |
| 最小报文开销 | 2 字节 | 头部数百字节 | 4 字节 | 帧头 2 字节起 |
| 云端主动推送 | 原生支持 | 不支持(需轮询改造) | 需配合 Observe | 支持 |
| 消息可靠性机制 | 内置三级 QoS | 依赖 TCP | 可选确认/重传 | 无,需自建 |
| 低功耗适配 | 优秀 | 较差 | 优秀(UDP 更省电) | 一般 |
| 典型适用场景 | 设备上云、遥测、远程控制 | 网页、开放 API、文件传输 | 资源极度受限的传感网 | 网页实时交互、聊天室 |
一句话定位:HTTP 是给人用的,WebSocket 是给浏览器用的,CoAP 是给极限受限设备用的,MQTT 是给"海量设备 + 弱网 + 双向实时"场景用的。
七、典型应用场景:你可能每天都在用
- 智能家居:MQTT 最大的基本盘。开源平台 Home Assistant 里大量设备通过 MQTT 接入;你家里的灯、插座、温湿度计,很可能此刻就在和某个 Broker 保持长连接。
- 工业物联网(IIoT):产线上的 PLC、机床、仪表把数据上报到厂级 Broker,MES 系统和监控大屏按需订阅。阿里云 IoT、AWS IoT Core 等云平台,设备接入层的主协议都是 MQTT。
- 车联网:车队管理平台通过 MQTT 向成千上万台车下发指令、收集车况,QoS 分级正好匹配"位置上报可丢、远程锁车必须到"的差异化诉求。
- 环境与农业监测:田间地头的土壤传感器、水库边的水质监测站靠电池和太阳能运行,MQTT 的低功耗与断线缓存能力是刚需。
八、上手实践:十分钟跑通你的第一条 MQTT 消息
纸上得来终觉浅,动手的门槛其实非常低。
选 Broker
- EMQX:国产开源,性能强悍、文档中文友好,还有在线公共测试 Broker
broker.emqx.io,练手首选。 - Mosquitto:Eclipse 基金会项目,C 语言编写,极轻量,树莓派上都能跑,适合本地调试。
- HiveMQ:Java 系企业级方案,商业支持完善。
选客户端工具
- MQTTX:EMQ 出品的跨平台桌面客户端(也有 CLI 和 Web 版),界面直观,调协议必备。
- mqtt-cli / mosquitto_pub、mosquitto_sub:命令行党的趁手工具。
一段能跑的 Python 示例
安装依赖:pip install paho-mqtt
订阅端(subscriber.py):
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, reason_code, properties):
print("已连接:", reason_code)
client.subscribe("home/livingroom/temperature", qos=1)
def on_message(client, userdata, msg):
print(f"收到 [{msg.topic}] {msg.payload.decode()}")
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.emqx.io", 1883, 60)
client.loop_forever()发布端(publisher.py):
import paho.mqtt.client as mqtt
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.connect("broker.emqx.io", 1883, 60)
client.publish("home/livingroom/temperature", "26.5", qos=1)
client.disconnect()
print("已发送")先跑订阅端,再跑发布端,你就能在订阅端的终端里看到那条"26.5"——这就是物联网世界最小的一次"心跳"。
最后提醒一句:公共测试 Broker 是所有人共享的,千万别往上面发任何敏感数据;正式项目请自建或购买 Broker 服务,并务必开启 TLS 加密与账号鉴权。
九、总结
MQTT 的成功不在于它有多先进,而在于它极度克制:在"石油管道 + 卫星链路"这种苛刻环境里被倒逼出来的小报文、低功耗、弱网韧性,恰好命中了天量物联网设备的核心诉求。发布/订阅的解耦模型、三级 QoS 的灵活可靠性、遗嘱与保留消息这些围绕"设备会掉线"的务实设计,让它成了今天物联网事实上的标准协议。
如果你正在做智能硬件或后端开发,我的建议是:先用公共 Broker 和 MQTTX 把发布/订阅跑一遍,再认真读一遍 QoS 和会话机制——这两块吃透,MQTT 的八成就到手了。
三十年前那根横跨荒原的石油管道大概不会想到,为它设计的小协议,今天正跑在数十亿台设备上。技术的生命力,往往就藏在这种"刚刚好"的设计里。
延伸学习资源
- MQTT 官方规范(OASIS):https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
- MQTT 官网与入门教程:https://mqtt.org/
- HiveMQ MQTT Essentials 系列教程(英文,体系完整):https://www.hivemq.com/mqtt/
- 电子/嵌入式论坛:https://bbs.eeclub.top/
推荐阅读
- 高性价比和便宜的VPS/云服务器推荐: https://blog.zeruns.com/archives/383.html
- 各家AI大模型API平台推荐与简介: https://blog.zeruns.com/archives/947.html
- 我的世界服务器搭建教程: https://blog.zeruns.com/tag/mc/
- Hermes Agent 部署全指南,手把手教你搭建你的第一个AI助手:https://blog.zeruns.com/archives/939.html
- 绿联(Ugreen)DXP4800Pro NAS 开箱评测与拆解:https://blog.zeruns.com/archives/949.html
- 运算放大器(Op-Amp)入门指南:从原理到实战:https://blog.zeruns.com/archives/938.html







