物联网为什么不用HTTP,而更喜欢 MQTT?
HTTP 已经统治互联网几十年,为什么到了物联网领域,我们却经常看到 MQTT?
ESP32、STM32、树莓派、智能家居、工业设备、传感器、网关为什么喜欢 MQTT?
MQTT 到底比 HTTP 好在哪里?
HTTP 能不能做物联网?
MQTT 为什么要设计 Publisher、Subscriber、Broker、Topic、QoS?
本文不从“MQTT 是一种轻量级协议”这种定义开始,而是从一个最根本的问题开始:
如果我们有 10 万个物联网设备,到底应该怎么让它们和服务器通信?
一、先说结论:物联网不是“不用 HTTP”,而是很多场景下 MQTT 更合适
首先纠正一个非常容易产生的误解:
物联网并不是不能使用 HTTP。
事实上,HTTP 在物联网中依然大量存在。
例如:
设备
↓ HTTP POST
服务器
完全可以。
ESP32 也可以:
HTTPClient http;
http.begin("https://example.com/api/device/data");
http.addHeader("Content-Type", "application/json");
int code = http.POST(
"{\"temperature\":25.6}"
);
服务器同样可以接收:
POST /api/device/data HTTP/1.1
Content-Type: application/json
{
"temperature": 25.6
}
所以问题并不是:
HTTP 能不能做 IoT?
答案是:
当然可以。
真正的问题是:
当设备数量变多、设备需要持续在线、数据需要实时上报、服务器需要主动下发命令、网络不稳定、设备资源有限的时候,HTTP 还是不是最合适的通信模型?
这时候 MQTT 的优势就开始出现了。
二、先从一个最简单的物联网场景开始
假设我们现在有一个温度传感器。
每 5 秒读取一次温度:
25.1℃
25.2℃
25.3℃
25.4℃
25.2℃
...
我们的目标是:
ESP32
↓
服务器
↓
数据库
↓
Web 管理后台
看起来非常简单。
我们甚至可以直接设计一个 HTTP API:
POST /api/device/temperature
请求:
{
"deviceId": "ESP32-001",
"temperature": 25.3,
"timestamp": 1778500000000
}
服务器:
@PostMapping("/api/device/temperature")
public void report(@RequestBody TemperatureReport request) {
System.out.println(
"设备:" + request.getDeviceId()
+ " 温度:" + request.getTemperature()
);
}
这完全没有问题。
那么为什么还需要 MQTT?
答案就藏在一个问题里面:
服务器怎么主动告诉 ESP32?
三、HTTP 最大的问题:它天然是 Request / Response 模型
HTTP 的核心通信模式是:
Client
|
| Request
v
Server
|
| Response
v
Client
IETF 的 HTTP 标准 RFC 9110 对 HTTP 的定义就是:
HTTP 是一种无状态的 request/response 协议。
HTTP 的基本模型就是:
客户端发送 Request
↓
服务器处理
↓
服务器返回 Response
RFC 9110 明确规定了 HTTP 的请求与响应语义:客户端发送 request,服务器处理后返回 response。

四、问题来了:服务器想主动控制设备怎么办?
假设现在有一个智能灯。
设备:
ESP32
服务器:
Java
Spring Boot
我们希望:
用户点击后台按钮
↓
服务器
↓
关闭灯
↓
ESP32
但是 HTTP 的天然模型是:
客户端 → 请求 → 服务器
服务器 → 响应 → 客户端
服务器并不能简单地:
Server
↓
HTTP POST
↓
ESP32
因为普通 HTTP 场景下,设备通常是 HTTP Server 的客户端,而不是一个等待服务器请求的 HTTP 服务端。
当然,我们可以让 ESP32 开放 HTTP Server:
ESP32 : 8080
然后:
Java Server
↓
HTTP POST
↓
ESP32
但现实中的 IoT 设备通常处于:
家庭路由器
↓
NAT
↓
互联网
设备往往没有一个公网 IP。
于是服务器很难直接找到设备。
五、有人可能会说:那就让设备一直轮询 HTTP
这是最经典的解决方案。
设备:
每 1 秒:
GET /api/device/command
服务器:
{
"command": null
}
过 1 秒:
GET /api/device/command
服务器:
{
"command": null
}
又过 1 秒:
GET /api/device/command
服务器:
{
"command": null
}
直到某一次:
{
"command": "LIGHT_OFF"
}
设备终于收到:
关闭灯
看起来解决了。
但是问题也来了。
六、HTTP 轮询到底浪费在哪里?
假设:
10000 台设备
每台设备:
每 1 秒请求一次
那么:
10000 × 60 × 60
一个小时就是:
36,000,000
次 HTTP 请求。
一天:
864,000,000
次请求。
关键是:
绝大部分请求其实没有数据。
例如:
设备 001 → 有命令吗?没有。
设备 002 → 有命令吗?没有。
设备 003 → 有命令吗?没有。
设备 004 → 有命令吗?没有。
...
这是一种非常典型的:
无效轮询。
七、HTTP 的设计目标和 IoT 的需求,本来就不完全一样
HTTP 是为了 Web 世界发展起来的。
它非常擅长:
浏览网页
REST API
文件传输
Web 服务
资源获取
前后端通信
例如:
GET /api/products
非常合理。
客户端说:
我要商品。
服务器:
给你商品。
但是 IoT 很多时候不是这种模式。
IoT 更像:
设备:
我刚刚测到了 25.6℃。
然后:
服务器:
收到。
同时服务器可能突然说:
服务器:
把继电器打开。
设备:
收到。
甚至还有:
设备 A
设备 B
设备 C
设备 D
全部都需要接收:
topic = building/1/floor/2/light
这样的消息。
这已经不是单纯的:
Request → Response
问题了。
八、MQTT 的核心思想:不要让设备一直问“有没有消息”
MQTT 换了一种思路。
不是:
设备:
服务器,有消息吗?
服务器:
没有。
设备:
服务器,有消息吗?
服务器:
没有。
设备:
服务器,有消息吗?
服务器:
没有。
而是:
设备:
我订阅这个主题。
服务器:
好的。
...
服务器有消息:
服务器
↓
Broker
↓
设备
这就是 MQTT 最核心的:
Publish / Subscribe
也就是:
发布 / 订阅模型。
OASIS 的 MQTT 5.0 标准明确将 MQTT 定义为:
Client Server publish/subscribe messaging transport protocol
并明确指出,发布/订阅模式可以实现一对多消息分发和应用之间的解耦。
九、MQTT 到底有几个角色?
MQTT 最重要的三个概念:
Publisher
Subscriber
Broker
中文:
发布者
订阅者
消息代理
例如:
温度传感器
↓
Publisher
↓
MQTT
↓
Broker
↓
Subscriber
↓
Java服务器
或者:
Java服务器
↓
Publisher
↓
MQTT Broker
↓
Subscriber
↓
ESP32
十、什么是 Broker?
Broker 可以理解成:
MQTT 世界里的消息中转站。
例如:
ESP32
↓
发布消息
↓
┌──────────────┐
│ MQTT Broker │
└──────────────┘
↓
订阅者
常见的 Broker:
EMQX
Mosquitto
HiveMQ
VerneMQ
Broker 负责:
连接管理
消息接收
Topic 路由
订阅管理
QoS 处理
会话管理
权限控制
因此 MQTT 的通信模型从:
Device → Server
变成:
Device → Broker → Subscriber
十一、这时候一个非常重要的问题来了:为什么不直接设备连服务器?
因为 MQTT 最重要的一个设计思想就是:
解耦。
假设有:
10000 个设备
如果全部直接连接业务服务器:
ESP32-001 ─┐
ESP32-002 ─┤
ESP32-003 ─┤
ESP32-004 ─┤
... ├── Java Server
ESP32-9999 ┤
ESP32-10000┘
那么业务服务器需要负责:
设备连接
认证
心跳
消息
离线
重连
路由
业务系统会越来越复杂。
而 MQTT:
┌── Device
│
├── Device
Device ── Broker ───┼── Device
│
├── Java
│
└── Web
Broker 专门负责:
消息通信。
业务服务器专门负责:
业务逻辑。
这就是解耦。
十二、Topic:MQTT 最重要的设计之一
MQTT 不直接把消息发送给:
deviceId
而是发送到:
Topic
例如:
home/livingroom/temperature
设备发布:
Topic:
home/livingroom/temperature
Payload:
25.6
另一个客户端订阅:
home/livingroom/temperature
就可以收到:
25.6
十三、Topic 到底是什么?
可以把 Topic 理解成:
消息频道。
例如:
home/livingroom/temperature
可以拆成:
home
└── livingroom
└── temperature
再比如:
device/001/status
device/001/temperature
device/001/humidity
device/001/command
我们甚至可以设计成:
iot/
├── device/
│ ├── 001/
│ │ ├── status
│ │ ├── telemetry
│ │ └── command
│ │
│ └── 002/
│ ├── status
│ ├── telemetry
│ └── command
这样整个物联网系统就有了一个非常清晰的消息命名空间。
十四、MQTT 的通配符非常适合 IoT
MQTT 支持 Topic Filter。
例如:
device/+/temperature
其中:
+
表示单层通配符。
因此:
device/001/temperature
device/002/temperature
device/003/temperature
都可以匹配。
还有:
#
多层通配符。
例如:
device/#
可以匹配:
device/001/status
device/001/temperature
device/002/status
device/002/temperature
MQTT 5.0 标准明确规定了 Topic Filter 和通配符订阅机制。
十五、一个非常经典的 MQTT 场景
假设:
1000 个温度传感器
全部发布:
building/1/temperature/{deviceId}
例如:
building/1/temperature/001
building/1/temperature/002
building/1/temperature/003
现在:
Java服务器
订阅:
building/1/temperature/#
那么所有温度数据都可以进入 Java 服务。
与此同时:
数据分析服务
也可以订阅:
building/1/temperature/#
而:
监控系统
也可以订阅:
building/1/temperature/#
于是:
┌── Java
│
Sensor ─ Broker ─ Analytics
│
└── Monitoring
发布者完全不需要知道:
Java 在哪里
Analytics 在哪里
Monitoring 在哪里
这就是:
发布者和消费者解耦。
十六、HTTP 和 MQTT 最核心的区别
现在可以正式比较两者。
| 对比项 | HTTP | MQTT |
|---|---|---|
| 通信模型 | Request / Response | Publish / Subscribe |
| 中间代理 | 可有可无 | Broker 是核心 |
| 消息方向 | 典型为客户端请求 | 双向消息 |
| 一对多 | 需要额外设计 | 天然支持 |
| Topic | 没有 | 核心机制 |
| QoS | 不提供 MQTT 那种消息级 QoS | QoS 0/1/2 |
| Retain | 无原生对应机制 | 支持 |
| Will | 无原生对应机制 | 支持 |
| IoT 设备通信 | 可以 | 非常适合 |
| Web API | 非常适合 | 通常不如 HTTP |
| 浏览器原生支持 | 强 | 通常通过 WebSocket |
| 典型用途 | REST API/Web | IoT/M2M/实时消息 |
HTTP 的标准模型是无状态的 Request/Response;MQTT 则以 Publish/Subscribe 为核心,并提供 QoS、Retain、Session 等针对消息通信设计的机制。
十七、为什么 MQTT 特别适合弱网环境?
物联网和互联网应用有一个非常明显的区别:
服务器通常:
CPU 很强
内存很多
网络稳定
电源稳定
但是设备可能:
ESP32
STM32
传感器
4G 模块
NB-IoT
Wi-Fi
电池供电
低功耗
设备可能:
掉线
断网
网络抖动
信号弱
带宽低
因此 IoT 协议必须考虑:
设备可能随时断开。
MQTT 从设计上就考虑了这种场景。
OASIS 标准明确指出,MQTT 设计目标包括资源受限环境和网络带宽受限的 M2M/IoT 场景。
十八、MQTT 为什么叫 Lightweight?
MQTT 的一个重要定位就是:
轻量级。
注意:
“轻量级”不是说 MQTT 完全没有协议头。
而是:
相比很多面向通用 Web 的通信协议,MQTT 的协议模型和控制报文更加针对消息传输场景。
MQTT 的固定头部非常紧凑。
例如 MQTT PUBLISH 报文的固定头中包含:
DUP
QoS
RETAIN
Remaining Length
OASIS MQTT 5.0 标准详细规定了 MQTT Control Packet 的结构以及 PUBLISH、SUBSCRIBE 等报文。
十九、QoS:MQTT 最重要的能力之一
如果你真正学习 MQTT,一定绕不开:
QoS
QoS:
Quality of Service
MQTT 定义了三个等级:
QoS 0
QoS 1
QoS 2
分别对应:
QoS 0
最多一次
QoS 1
至少一次
QoS 2
恰好一次
OASIS MQTT 5.0 标准明确规定了这三个 QoS 等级。
二十、QoS 0:At Most Once
QoS 0:
最多一次
发送:
Publisher
|
| PUBLISH
↓
Broker
没有:
PUBACK
也不会进行 MQTT 层面的重试。
因此:
可能收到
也可能丢失
适合:
实时温度
实时湿度
实时空气质量
实时位置
例如:
25.1℃
25.2℃
25.3℃
如果:
25.2℃
丢了一条。
问题不大。
因为:
25.3℃
马上又来了。
MQTT 标准甚至以环境传感器数据作为 QoS 0 的典型适用场景。
二十一、QoS 1:At Least Once
QoS 1:
至少一次
流程:
Publisher
|
| PUBLISH
↓
Broker
|
| PUBACK
↓
Publisher
如果没有收到:
PUBACK
发送方可能重新发送。
因此:
消息至少送到一次。
但是:
可能重复。
例如:
服务器收到:
订单支付成功
因为 ACK 丢失。
设备重新发送:
订单支付成功
服务器可能收到两次。
所以 QoS 1 的业务代码必须考虑:
幂等性。
例如:
if (alreadyProcessed(messageId)) {
return;
}
process(message);
markProcessed(messageId);
二十二、QoS 2:Exactly Once
QoS 2:
恰好一次
这是最高级别的 MQTT QoS。
它会进行更加完整的握手:
PUBLISH
↓
PUBREC
↓
PUBREL
↓
PUBCOMP
也就是:
Publisher
|
| PUBLISH
↓
Broker
|
| PUBREC
↓
Publisher
|
| PUBREL
↓
Broker
|
| PUBCOMP
↓
Publisher
因此 QoS 2 的协议开销更大。
OASIS 标准明确说明 QoS 2 用于既不能丢失也不能接受重复的消息,但其开销高于 QoS 0/1。
二十三、千万不要认为 QoS 2 就等于“业务绝对不会重复”
这是学习 MQTT 时非常重要的一个细节。
MQTT 的:
Exactly Once
是:
MQTT 消息传递语义层面的 Exactly Once。
并不自动意味着:
数据库业务
支付业务
订单业务
就一定不会重复。
例如:
MQTT
↓
Java
↓
MySQL
即使 MQTT 消息只交付一次。
你的 Java 程序仍然可能:
消费成功
↓
数据库提交成功
↓
程序崩溃
↓
业务状态没有正确记录
因此生产系统仍然需要:
幂等
事务
消息 ID
唯一约束
状态机
二十四、MQTT Retain:为什么新上线的设备也能马上知道状态?
这是 MQTT 非常有意思的一个能力。
假设:
Topic:
home/livingroom/light/status
当前灯是:
ON
设备发布:
ON
并设置:
RETAIN = true
Broker 会保存这个 Topic 的最后一条 retained message。
此时:
一个新的客户端
刚刚订阅:
home/livingroom/light/status
Broker 就可以把之前保存的:
ON
立即发给它。
二十五、Retain 到底解决什么问题?
没有 Retain:
设备:
我现在 ON。
↓
客户端当时没在线
↓
客户端后来上线
↓
不知道当前状态
有 Retain:
设备:
ON
↓
Broker 保存
↓
客户端后来上线
↓
Subscribe
↓
Broker 立即发送 ON
这特别适合:
设备在线状态
开关状态
温度当前值
设备配置
运行状态
MQTT 5.0 标准明确规定了 RETAIN 标志:Broker 保存指定 Topic 的 retained message,并在后续匹配订阅时提供该消息。
二十六、Retain 和数据库有什么区别?
Retain:
保存 Topic 的最新消息
数据库:
保存完整业务历史
例如:
MQTT Retain:
temperature = 25.6
数据库:
10:00 → 25.1
10:01 → 25.3
10:02 → 25.6
10:03 → 25.4
所以:
Retain 不是数据库。
它更像:
这个 Topic 的“最后已知状态”。
二十七、MQTT Last Will:设备突然掉线怎么办?
这是 MQTT 另一个非常适合 IoT 的能力:
Last Will and Testament
简称:
Will Message
中文一般叫:
遗嘱消息。
假设:
ESP32
正常在线。
它连接 MQTT Broker 时告诉 Broker:
如果我异常掉线,
请帮我发布:
device/001/status = offline
如果 ESP32 正常执行:
DISCONNECT
Broker 不应该因为正常断开而发布遗嘱。
但是如果:
Wi-Fi 断开
设备死机
突然断电
网络断开
Broker 判断连接异常终止后,就可以发布:
offline
二十八、Will Message 对 IoT 有多重要?
比如:
device/001/status
可以设计:
online
offline
设备启动:
online
异常掉线:
offline
于是管理后台就可以实时显示:
设备 001 在线
设备 002 在线
设备 003 离线
设备 004 在线
而不需要不断 HTTP 查询:
设备 001 在线吗?
设备 002 在线吗?
设备 003 在线吗?
这正是 MQTT 非常适合 IoT 的一个重要原因。
二十九、Keep Alive:MQTT 怎么知道设备还活着?
MQTT 还有一个:
Keep Alive
机制。
例如:
Keep Alive = 60 秒
意味着客户端与 Broker 在规定时间内需要保持通信活动。
MQTT 提供:
PINGREQ
PINGRESP
用于保持连接以及检测连接状态。
协议中定义了:
Client
|
| PINGREQ
↓
Broker
|
| PINGRESP
↓
Client
如果连接长期没有有效通信,客户端或服务器可以判断连接已经失效。
三十、MQTT 为什么适合“长连接”?
IoT 设备经常需要:
一直在线
一直监听
随时接收命令
因此 MQTT 通常建立一个持续的 TCP 连接:
ESP32
|
| TCP
|
MQTT Broker
然后:
温度来了
↓
PUBLISH
命令来了
↓
PUBLISH
状态变化
↓
PUBLISH
而不是每次数据都:
建立 HTTP 请求
发送
等待响应
结束
需要注意的是:
HTTP/1.1 本身也支持持久连接。
IETF RFC 9112 明确规定 HTTP/1.1 默认允许 persistent connections,一个连接上可以承载多个请求和响应。
所以不能简单说:
HTTP 没有长连接。
这是错误的。
真正的区别是:
HTTP 的核心语义依然是 Request/Response;MQTT 的核心语义是持续连接上的消息发布/订阅。
三十一、所以 MQTT 比 HTTP 快吗?
不能简单回答:
MQTT 一定比 HTTP 快。
这是一个非常常见的误区。
准确来说:
MQTT 在大量小消息、持续连接、实时消息分发、设备通信等场景下,通常具有更合适的协议模型和更低的通信开销。
而不是:
MQTT > HTTP
所有场景都成立。
例如:
下载 100 MB 文件
你显然不会因为 MQTT 轻量就选择 MQTT。
HTTP:
非常合适
MQTT:
并不适合
三十二、HTTP 和 MQTT 的本质不是“谁更快”
更准确的问题应该是:
这个通信场景是什么?
如果是:
Web API
文件下载
图片上传
REST
网页
资源访问
HTTP 非常合适。
如果是:
传感器
设备状态
实时消息
设备控制
一对多
持续在线
弱网
MQTT 往往更加合适。
三十三、一个完整的 IoT MQTT 架构
假设我们开发一个智能家居系统:
Internet
|
MQTT Broker
|
+----------------+----------------+
| | |
↓ ↓ ↓
ESP32 ESP32 ESP32
客厅灯 卧室灯 温度计
后面再接:
MQTT Broker
|
+---------+---------+
| |
↓ ↓
Java Backend Data Service
|
↓
MySQL
|
↓
Web Admin
完整结构:
┌──────────────┐
│ Web Admin │
└──────┬───────┘
↓
┌──────────────┐
│ Java Backend │
└──────┬───────┘
↓
┌──────────────┐
│ MQTT Broker │
└──────┬───────┘
↓
┌─────────────┼─────────────┐
↓ ↓ ↓
ESP32-001 ESP32-002 ESP32-003
三十四、Java 后端为什么非常适合接 MQTT?
假设你本身是 Java 开发者。
你完全可以:
Spring Boot
+
MQTT Client
+
EMQX / Mosquitto
例如:
Spring Boot
|
| MQTT Client
↓
MQTT Broker
|
+── ESP32
+── STM32
+── Gateway
这样 Java 不需要自己实现:
MQTT Server
而是作为:
MQTT Client / Subscriber / Publisher
连接 Broker。
三十五、Java 订阅 MQTT 的基本思想
例如:
mqttClient.subscribe(
"device/+/telemetry",
1
);
收到消息:
public void messageArrived(
String topic,
MqttMessage message) {
String payload =
new String(
message.getPayload(),
StandardCharsets.UTF_8
);
System.out.println(
topic + " => " + payload
);
}
如果设备发送:
device/001/telemetry
Java 就可以收到:
{
"temperature": 25.6,
"humidity": 60
}
三十六、设备向 MQTT 发布数据
ESP32 可以使用 MQTT 客户端库。
伪代码:
mqttClient.publish(
"device/001/telemetry",
"{\"temperature\":25.6}"
);
整个链路:
ESP32
↓
PUBLISH
↓
MQTT Broker
↓
Java Subscriber
↓
业务处理
↓
MySQL
三十七、服务器向设备发送命令
服务器发布:
Topic:
device/001/command
Payload:
{
"command": "LIGHT_ON"
}
ESP32 订阅:
device/001/command
于是:
Java
↓
MQTT PUBLISH
↓
Broker
↓
ESP32
↓
打开灯
整个过程中:
Java 根本不需要知道 ESP32 的 IP 地址。
这就是 MQTT 非常关键的价值。
三十八、这也是 MQTT 和 HTTP 最核心的区别之一
HTTP:
Server 想控制 Device
往往需要:
找到 Device
↓
建立连接
↓
发送 Request
MQTT:
Server
↓
Publish
↓
device/001/command
↓
Broker
↓
Device
服务器只需要知道:
Topic。
不需要知道设备在哪里。
三十九、这就是“位置”和“身份”的解耦
这是 MQTT 非常漂亮的设计。
设备:
device/001
无论它现在:
Wi-Fi A
4G
Wi-Fi B
家庭网络
公司网络
只要它连接到 Broker:
Broker
并订阅:
device/001/command
就可以收到命令。
因此:
Device Identity
与:
Network Location
被解耦了。
这对于 IoT 非常重要。
四十、MQTT 的安全性怎么样?
MQTT 本身并不意味着:
自动安全
通常需要:
MQTT
+
TLS
+
Authentication
+
Authorization
例如:
MQTT over TLS
常见端口:
1883
通常用于非 TLS MQTT。
而:
8883
常用于 MQTT over TLS。
MQTT 5.0 标准明确说明 TCP 1883 和 TLS 1883/8883 的注册使用,其中 8883 为 MQTT over TLS 的常见端口。
四十一、为什么 MQTT 必须做 Topic 权限控制?
假设:
device/001
只应该访问:
device/001/#
但是如果没有权限控制:
device/001
可能订阅:
device/002/command
甚至:
device/#
那就会产生非常严重的安全问题。
因此生产级 MQTT 必须设计:
Username
Password
Client ID
TLS
ACL
Topic Permission
例如:
device/001
允许:
device/001/telemetry
device/001/status
device/001/command
禁止:
device/002/#
system/#
admin/#
四十二、MQTT Topic 权限实际上非常适合多租户 IoT
假设:
tenant001
tenant002
tenant003
可以设计:
tenant/{tenantId}/device/{deviceId}/telemetry
例如:
tenant/10001/device/001/telemetry
Java 后端可以根据:
tenantId
进行权限控制。
这和 SaaS 多租户设计其实非常类似。
四十三、MQTT 与数据库应该怎么配合?
一个比较合理的架构:
ESP32
↓
MQTT
↓
Broker
↓
Java Consumer
↓
┌───────────────┐
│ Business Logic│
└───────┬───────┘
↓
MySQL
但是不要把所有实时数据都无脑写 MySQL。
例如:
10000 台设备
每秒上报一次
就是:
10000 messages / second
一年数据量非常大。
这时候应该考虑:
MQTT
↓
Message Processing
↓
Kafka / Pulsar
↓
Time Series DB
或者:
MQTT
↓
Stream Processing
↓
InfluxDB
TimescaleDB
ClickHouse
根据具体业务选择。
四十四、MQTT 并不是数据库
这一点必须再次强调。
MQTT:
消息传输协议
MySQL:
关系型数据库
Redis:
缓存 / 数据结构存储
Kafka:
分布式事件流平台
它们解决的问题完全不同。
所以:
MQTT
不是:
Kafka 的 IoT 版本
也不是:
Redis 的消息版
它首先是:
IoT/M2M 场景下的轻量级消息传输协议。
四十五、MQTT 和 Kafka 有什么区别?
这个问题在后端开发中非常常见。
| 对比 | MQTT | Kafka |
|---|---|---|
| 定位 | 消息传输协议 | 分布式事件流平台 |
| 主要对象 | IoT / Client | 后端服务 / 数据平台 |
| Broker | 核心 | Broker 集群 |
| Topic | 有 | 有 |
| QoS | MQTT QoS 0/1/2 | 不同可靠性机制 |
| 设备友好 | 很强 | 通常不适合直接跑在 MCU 上 |
| 持久化 | 有相关机制 | 核心能力之一 |
| 大规模日志流 | 一般 | 非常强 |
| IoT 接入 | 很适合 | 通常需要网关 |
| 数据分析 | 通常配合其他系统 | 很强 |
实际系统甚至可以:
ESP32
↓
MQTT
↓
EMQX
↓
Kafka
↓
Data Platform
这才是非常常见的企业级架构思路。
四十六、MQTT 和 WebSocket 有什么区别?
WebSocket:
双向通信
MQTT:
发布 / 订阅消息协议
可以理解为:
WebSocket
解决:
浏览器与服务器之间建立双向通信通道
而:
MQTT
解决:
IoT 客户端之间如何进行消息发布和订阅
MQTT 甚至可以运行在 WebSocket 之上。
OASIS MQTT 5.0 标准明确说明 MQTT 可以运行在提供有序、无损、双向字节流的底层传输之上,并列出了 TCP/IP、TLS、WebSocket 等方式。
四十七、一个真实的智能家居系统应该怎么设计?
假设:
ESP32
控制:
客厅灯
卧室灯
风扇
窗帘
温度传感器
人体传感器
可以设计:
home/
├── livingroom/
│ ├── light/
│ │ ├── command
│ │ └── state
│ └── temperature
│
├── bedroom/
│ ├── light/
│ │ ├── command
│ │ └── state
│ └── temperature
│
└── gateway/
└── status
四十八、设备状态 Topic
例如:
home/livingroom/light/state
Payload:
{
"power": true,
"brightness": 80
}
设置:
retain = true
这样新的客户端连接后,可以直接得到当前状态。
四十九、设备命令 Topic
例如:
home/livingroom/light/command
Payload:
{
"action": "TURN_ON"
}
ESP32:
Subscribe:
home/livingroom/light/command
收到:
{
"action": "TURN_ON"
}
然后:
GPIO HIGH
打开继电器。
五十、设备遥测 Topic
例如:
home/livingroom/sensor/telemetry
Payload:
{
"temperature": 25.6,
"humidity": 61.2
}
Java 后端:
Subscribe:
home/+/sensor/telemetry
即可接收所有房间的传感器数据。
五十一、设备在线状态 Topic
home/device/001/status
在线:
online
异常掉线:
offline
通过:
Will Message
实现。
五十二、最终形成一个非常漂亮的 IoT 通信模型
MQTT Broker
|
+-----------------+-----------------+
| | |
↓ ↓ ↓
Telemetry Command Status
| | |
↓ ↓ ↓
Device Device Device
服务器:
Java Backend
|
|
MQTT Client
|
↓
MQTT Broker
五十三、为什么 IoT 喜欢 MQTT?
现在我们可以真正回答最开始的问题。
因为 IoT 有很多特殊需求:
1. 设备数量巨大
2. 设备资源有限
3. 网络环境复杂
4. 设备可能随时掉线
5. 需要实时通信
6. 需要服务器主动下发
7. 一对多通信很常见
8. 需要设备状态管理
9. 需要离线处理
10. 需要低通信开销
而 MQTT 恰好针对其中很多问题提供了:
Publish / Subscribe
Broker
Topic
QoS
Retain
Will
Keep Alive
Session
所以:
不是 HTTP 不好。
而是:
MQTT 的通信模型更贴合很多 IoT 场景。
五十四、但是 HTTP 在 IoT 中依然非常重要
真正成熟的 IoT 系统一般不会:
全部 MQTT
更常见的是:
IoT Platform
|
+------------+------------+
| |
MQTT HTTP
| |
Device Management API
| |
Telemetry Web / App
Command Admin
Status Configuration
例如:
ESP32
↓ MQTT
设备数据
而:
Web
↓ HTTP
查询设备列表
又比如:
Web
↓ HTTP
修改设备名称
后端:
HTTP
↓
Java
↓
MQTT
↓
ESP32
于是:
HTTP
负责:
业务 API。
MQTT
负责:
设备消息。
这才是非常合理的架构。
五十五、一个典型的“HTTP + MQTT”架构
┌───────────────┐
│ Web / App │
└───────┬───────┘
│
HTTP
│
↓
┌────────────────┐
│ Java Backend │
└───────┬────────┘
│
┌──────────┴──────────┐
│ │
HTTP MQTT
│ │
↓ ↓
Business API MQTT Broker
│
┌─────────────┼─────────────┐
↓ ↓ ↓
ESP32 ESP32 ESP32
这套架构其实非常适合:
Spring Boot
+
EMQX
+
MySQL
+
Redis
+
Vue
+
ESP32
五十六、如果我作为是一个 Java + IoT 开发者,我会怎么设计?
如果让我从零设计一个 IoT 平台,我不会选择:
全部 HTTP
也不会选择:
全部 MQTT
而会选择:
Frontend
|
HTTP
|
Spring Boot
/ \
Redis MySQL
\
MQTT Client
|
MQTT Broker
|
+----------+----------+
| | |
ESP32 ESP32 Gateway
其中:
HTTP
负责:
用户
设备管理
用户管理
设备配置
查询
统计
权限
而:
MQTT
负责:
遥测
状态
命令
实时数据
设备上下线
设备事件
五十七、MQTT 最核心的知识点总结
如果你刚刚开始学习 MQTT,可以先记住下面这张表:
| 概念 | 作用 |
|---|---|
| Client | MQTT 客户端 |
| Broker | 消息代理服务器 |
| Publisher | 发布消息 |
| Subscriber | 订阅消息 |
| Topic | 消息主题 |
| PUBLISH | 发布消息 |
| SUBSCRIBE | 订阅主题 |
| QoS 0 | 最多一次 |
| QoS 1 | 至少一次 |
| QoS 2 | 恰好一次 |
| Retain | 保存 Topic 最新消息 |
| Will | 异常断线消息 |
| Keep Alive | 保持/检测连接 |
| Session | 保存客户端会话状态 |
| TLS | 加密通信 |
| ACL | Topic 权限控制 |
五十八、MQTT 的完整通信流程
一个典型 MQTT Client 生命周期:
Client
|
| CONNECT
↓
Broker
|
| CONNACK
↓
Client
|
| SUBSCRIBE
↓
Broker
|
| SUBACK
↓
Client
|
| PUBLISH
↓
Broker
|
| PUBLISH
↓
Subscriber
如果是 QoS 1:
PUBLISH
↓
PUBACK
如果是 QoS 2:
PUBLISH
↓
PUBREC
↓
PUBREL
↓
PUBCOMP
这就是 MQTT 最基本的协议交互。
五十九、MQTT 不是“更高级的 HTTP”
这一点非常重要。
很多初学者会认为:
HTTP
↓
MQTT
好像 MQTT 是 HTTP 的升级版。
不是。
它们解决的问题不同。
HTTP:
Request / Response
Resource
URI
Method
Status Code
MQTT:
Publish / Subscribe
Topic
Broker
QoS
Session
Retain
Will
它们是:
不同通信模型的协议。
六十、什么时候应该用 HTTP?
如果你的需求是:
用户登录
查询设备列表
查询历史数据
修改设备名称
上传图片
下载文件
管理后台
REST API
开放平台 API
优先考虑:
HTTP / HTTPS
六十一、什么时候应该用 MQTT?
如果你的需求是:
传感器实时上报
设备在线状态
远程控制
实时消息
大量设备
设备主动上报
服务器主动下发
弱网
长连接
一对多消息
优先考虑:
MQTT
六十二、什么时候两个都需要?
绝大多数完整 IoT 平台。
例如:
用户
↓
HTTPS
↓
Java Backend
↓
MQTT
↓
Device
设备:
Device
↓
MQTT
↓
Java Backend
查询:
Web
↓
HTTPS
↓
Java Backend
↓
MySQL
这是非常经典的:
HTTP + MQTT 双协议架构。
六十三、最终答案:为什么物联网经常不用 HTTP,而使用 MQTT?
现在终于可以给出一个完整答案。
并不是:
物联网不用 HTTP。
而是:
物联网的通信特点与 HTTP 的 Request/Response 模型并不总是匹配,而 MQTT 的 Publish/Subscribe 模型更加适合大量设备、实时消息、弱网、长连接、设备上下行通信等场景。
HTTP 擅长:
请求资源
调用 API
上传文件
下载数据
Web 服务
MQTT 擅长:
设备消息
实时数据
状态同步
远程控制
一对多通信
设备上下行
所以实际系统往往是:
User
|
HTTPS
|
Java Backend
/ \
/ \
MySQL MQTT
|
Broker
|
+---------------+---------------+
| | |
ESP32 ESP32 Gateway
这才是正确理解 MQTT 的方式。
六十四、从 HTTP 到 MQTT,本质上是通信思想的变化
HTTP 的思维:
我想要什么?
↓
我去请求服务器。
MQTT 的思维:
我关心什么?
↓
我订阅 Topic。
HTTP:
Client
↓
Request
↓
Server
↓
Response
MQTT:
Publisher
↓
Topic
↓
Broker
↓
Subscriber
这两个模型之间最大的区别,并不是:
代码写法不同
而是:
通信关系不同。
六十五、MQTT 真正伟大的地方:解耦
如果让我用一个词总结 MQTT:
解耦。
设备不需要知道:
谁在消费消息
消费者不需要知道:
设备在哪里
发布者不需要知道:
订阅者是谁
所有东西通过:
Broker
+
Topic
连接起来。
最终形成:
Topic
|
+----------+----------+
| | |
Device Java AI
| | |
+----------+----------+
|
Broker
这也是 MQTT 能够成为 IoT 领域重要通信协议的核心原因之一。
六十六、从 MQTT 再往前一步:IoT 平台真正的核心是什么?
如果继续往后学习 IoT,你会发现:
MQTT 其实只是第一步。
真正完整的 IoT 平台还需要:
Device Management
设备管理
Device Authentication
设备认证
Device Provisioning
设备注册
Device Shadow
设备影子
OTA
固件升级
Rule Engine
规则引擎
Event Processing
事件处理
Data Storage
数据存储
Alarm
告警
Dashboard
数据可视化
AI
智能分析
最终形成:
IoT Platform
|
+----------------+----------------+
| | |
Device Data AI
Management Platform Engine
| | |
+----------------+----------------+
|
MQTT
|
MQTT Broker
|
+------------+------------+
| | |
ESP32 STM32 Gateway
所以:
MQTT 不是物联网平台。
MQTT 是物联网平台非常重要的一条通信基础设施。
六十七、如果你正在学习 IoT,建议这样学习 MQTT
建议不要一上来就背:
QoS
Retain
Will
Session
而是按照下面的路线学习。
第一阶段:理解通信模型
先理解:
HTTP
Request / Response
然后:
MQTT
Publish / Subscribe
真正理解两者为什么不同。
第二阶段:理解 MQTT 核心组件
掌握:
Client
Broker
Publisher
Subscriber
Topic
第三阶段:掌握消息可靠性
重点学习:
QoS 0
QoS 1
QoS 2
并理解:
为什么 QoS 1 会重复?
为什么业务需要幂等?
为什么 QoS 2 开销更高?
第四阶段:掌握 IoT 状态机制
学习:
Retain
Will
Keep Alive
Session
第五阶段:掌握安全
学习:
TLS
Authentication
Authorization
ACL
Topic Permission
第六阶段:和 Java 结合
学习:
Spring Boot
+
MQTT Client
+
EMQX
实现:
设备上报
设备订阅
服务端下发
设备上下线
数据入库
第七阶段:连接真实硬件
例如:
ESP32
+
温度传感器
+
MQTT
+
EMQX
+
Spring Boot
+
MySQL
+
Vue
做出一个真正可以运行的 IoT 项目。
六十八、一个真正值得做的 MQTT 实战项目
如果你准备把 MQTT 学透,我非常推荐做这样一个项目:
“基于 ESP32 + MQTT + Spring Boot 的物联网设备管理平台”
架构:
Vue
|
HTTP
|
Spring Boot
/ \
/ \
MySQL MQTT Client
|
EMQX Broker
|
+-----------+-----------+
| | |
ESP32 ESP32 ESP32
| | |
Sensor Sensor Relay
功能:
设备注册
设备认证
设备在线
设备离线
温度上报
湿度上报
远程开关
设备日志
历史数据
实时数据
MQTT QoS
Retain
Will
OTA
这个项目做完以后,MQTT 基本就不是停留在“知道概念”的阶段了。
而是真正进入:
能设计 IoT 系统。
六十九、最后总结
如果整篇文章只记住下面这张图,就已经足够了:
HTTP
Client
|
Request
|
↓
Server
|
Response
|
↓
Client
HTTP 是:
请求 / 响应。
而 MQTT:
MQTT
Publisher
|
Publish
|
↓
Topic
|
↓
Broker
|
+------------+
| |
↓ ↓
Subscriber Subscriber
MQTT 是:
发布 / 订阅。
再往上:
HTTP
↓
业务 API
MQTT
↓
设备消息
Broker
↓
设备通信
QoS
↓
消息可靠性
Retain
↓
最新状态
Will
↓
异常掉线
Keep Alive
↓
连接状态
TLS + ACL
↓
安全
所以,物联网为什么经常使用 MQTT?
不是因为:
MQTT 比 HTTP 高级。
也不是因为:
HTTP 不能做物联网。
真正原因是:
物联网面对的是大量设备、持续连接、实时消息、上下行通信、弱网络环境以及一对多消息分发,而 MQTT 的 Publish/Subscribe + Broker + Topic + QoS 等机制,天然更贴合这些通信需求。
HTTP 解决的是:
客户端如何请求服务器资源。
MQTT 解决的是:
大量设备和服务之间如何高效地交换消息。
当你真正理解这一点之后,MQTT 就不再是一堆:
QoS
Topic
Retain
Will
Broker
这些零散概念。
你会发现:
MQTT 的每一个设计,几乎都在回答 IoT 世界里的一个真实问题。
七十、官方标准与参考资料
本文主要参考以下官方标准与权威资料。
1. OASIS MQTT 5.0 官方标准
MQTT 5.0 是 OASIS 标准,完整定义了:
MQTT Client / Server
Publish / Subscribe
Topic
QoS
Retain
Will
Session
Keep Alive
Flow Control
官方标准:
https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
2. OASIS MQTT 3.1.1 官方标准
MQTT 3.1.1 同样是 OASIS 标准,也是大量 MQTT 实际项目长期使用的重要版本。
官方标准:
https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html
3. IETF RFC 9110:HTTP Semantics
RFC 9110 定义了现代 HTTP 的核心语义,并明确说明 HTTP 是一种:
stateless
request/response
协议。
官方:
https://www.rfc-editor.org/rfc/rfc9110.html
4. IETF RFC 9112:HTTP/1.1
RFC 9112 定义 HTTP/1.1 消息语法和连接管理,并明确说明 HTTP/1.1 默认支持 persistent connections。
官方:
https://www.rfc-editor.org/rfc/rfc9112.html
更多推荐


所有评论(0)