跳转到内容

MQTT 协议概述

本节介绍 MQTT(Message Queuing Telemetry Transport)协议的基本概念、历史背景和在 IoT 中的应用。学习完成后,您将能够:

  • 理解 MQTT 协议的核心设计理念
  • 掌握 MQTT 的关键术语和概念
  • 了解 MQTT 在 IoT 系统中的架构角色
  • 认识 MQTT 的主要特性和优势

在开始本节之前,请确保:

  • 了解基本的网络概念(IP、端口、客户端-服务器模型)
  • 已完成 Docker 环境搭建
  • 已安装 MQTT Broker(如 Mosquitto 或 EMQX)

MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传递协议,专为以下场景设计:

  • 低带宽:适用于网络带宽受限的环境
  • 高延迟:在网络延迟较高的情况下仍能可靠工作
  • 不可靠连接:能够处理不稳定的网络连接

MQTT 采用**发布-订阅(Publish-Subscribe)**模式,与传统的请求-响应模式不同,这种架构使设备能够高效地进行一对多通信。

  • 开发时间:1999 年
  • 开发者:IBM 和 Arcom(现为 Eurotech)
  • 初始用途:监控和控制远程设备
  • 现代应用:IoT、智能家居、工业物联网、移动应用

MQTT 最初设计用于通过卫星链路监控石油管道,现在已成为 IoT 领域最广泛使用的协议之一。

MQTT 架构包含三个核心组件:

  1. Publisher(发布者)

    • 发送消息的设备或应用
    • 将消息发布到特定的 Topic
    • 示例:ESP32 温度传感器发布温度数据
  2. Broker(代理服务器)

    • 处理所有消息的路由和分发
    • 维护客户端连接状态
    • 示例:Eclipse Mosquitto、EMQX、HiveMQ
  3. Subscriber(订阅者)

    • 接收消息的设备或应用
    • 订阅感兴趣的 Topic
    • 示例:Node-RED、手机应用、数据库
ESP32 (Publisher)
|
| Publish: Topic="home/temperature", Payload="25.5"
[MQTT Broker]
|
| Route message to all subscribers
Node-RED (Subscriber) ← Receives: "25.5"
Grafana (Subscriber) ← Receives: "25.5"
Database (Subscriber) ← Receives: "25.5"

工作流程

  1. Publisher 将消息发布到 Broker 的特定 Topic
  2. Broker 接收消息并根据 Topic 进行路由
  3. Broker 将消息发送给所有订阅了该 Topic 的 Subscriber
  4. Subscriber 接收并处理消息

Topic 是消息的目标地址,采用层级结构,使用斜杠 / 分隔:

示例 Topic 结构:
home/groundfloor/office/temperature
home/groundfloor/kitchen/humidity
home/firstfloor/bedroom/light/status

特点

  • 区分大小写
  • 可以包含字母、数字、斜杠
  • 层级结构便于消息过滤和组织

Payload 是消息的实际内容,可以是:

  • 字符串"25.5"
  • JSON{"temperature": 25.5, "humidity": 60}
  • 二进制数据:图像、音频等
  • 数字42

注意:ESP32 等微控制器的 payload 大小通常受限于网络带宽和内存。

QoS 定义了消息传递的可靠性级别(详细内容见后续小节):

  • QoS 0:At most once(最多一次)- 快速但可能丢失
  • QoS 1:At least once(至少一次)- 可靠但可能重复
  • QoS 2:Exactly once(恰好一次)- 最可靠但最慢

Broker 会保存最后一个发布的保留消息。当新的 Subscriber 订阅该 Topic 时,会立即收到这条消息。

使用场景

  • 设备状态(在线/离线)
  • 最后已知的传感器值
  • 配置信息
  1. 轻量级

    • 最小消息头仅 2 字节
    • 低带宽消耗
    • 适合资源受限的设备
  2. 发布-订阅模式

    • 解耦发布者和订阅者
    • 支持一对多通信
    • 易于扩展
  3. 多平台支持

    • C/C++(Arduino、ESP32)
    • Python
    • JavaScript/Node.js
    • Java
    • PHP
    • 等…
  4. 开源生态

    • Eclipse Mosquitto(Broker)
    • 多种客户端库
    • 活跃的社区支持
  5. 灵活性

    • 适用于各种网络条件
    • 支持持久会话
    • 可选的消息确认机制
特性MQTTHTTP
模式发布-订阅请求-响应
开销低(2 字节头)高(数百字节头)
实时性高(推送)低(轮询)
带宽
一对多原生支持需要额外实现
离线消息支持(QoS + 保留)不支持
[ESP32 Sensors] ──┐
[ESP32-CAM] ──────┼─── Publish ──→ [Mosquitto Broker] ──→ Subscribe ──→ [Node-RED]
│ ↓
[Smart Plugs] ────┘ [InfluxDB] + [Grafana]

数据流

  1. ESP32 传感器采集数据
  2. 通过 MQTT 发布到 Broker
  3. Node-RED 订阅并处理数据
  4. 数据存储到 InfluxDB
  5. Grafana 可视化展示
  1. 智能家居

    • 传感器数据采集
    • 设备远程控制
    • 自动化场景
  2. 工业监控

    • 设备状态监控
    • 告警通知
    • 数据采集
  3. 农业 IoT

    • 环境监测
    • 自动灌溉
    • 温室控制
  4. 可穿戴设备

    • 健康数据上传
    • 实时通知
    • 设备同步

确保 Mosquitto Broker 已安装并运行:

Terminal window
# 检查 Docker 容器状态
docker ps | grep mosquitto

预期输出

CONTAINER ID IMAGE COMMAND STATUS PORTS
abc123def456 eclipse-mosquitto "/docker-entrypoint.…" Up 2 hours 0.0.0.0:1883->1883/tcp

使用命令行工具测试 MQTT 连接:

Terminal window
# 进入 Mosquitto 容器
docker exec -it mosquitto sh
# 测试发布消息
mosquitto_pub -h localhost -t "test/topic" -m "Hello MQTT"
# 测试订阅消息(另一个终端)
mosquitto_sub -h localhost -t "test/topic"

预期输出

# 订阅端将显示:
Hello MQTT

创建结构化的 Topic:

Terminal window
# 发布温度数据
mosquitto_pub -h localhost \
-t "home/groundfloor/office/temperature" \
-m '{"value": 25.5, "unit": "celsius"}'
# 订阅整个 home 的所有消息
mosquitto_sub -h localhost -t "home/#"
# 只订阅所有房间的温度
mosquitto_sub -h localhost -t "home/+/temperature"

验证对 MQTT 协议的理解:

  1. 架构理解

    • 能解释 Publisher、Broker、Subscriber 的角色
    • 理解发布-订阅模式的优势
    • 知道 Topic 的层级结构
  2. 术语掌握

    • 理解 Topic、Payload、QoS 的含义
    • 知道保留消息的作用
    • 了解三种 QoS 级别的区别
  3. 实际操作

    • 能使用命令行发布和订阅消息
    • 能设计合理的 Topic 结构
    • 能验证 Broker 运行状态

Symptom:

Error: Connection refused

Possible Causes:

  • Mosquitto 容器未运行
  • 端口被占用
  • 防火墙阻止连接

Solution:

Terminal window
# 1. 检查容器状态
docker ps | grep mosquitto
# 2. 如果未运行,启动容器
docker start mosquitto
# 3. 检查端口占用
lsof -i :1883
# 4. 测试本地连接
telnet localhost 1883

Symptom:

  • 发布消息成功
  • 订阅端未收到消息

Possible Causes:

  • Topic 不匹配
  • QoS 设置问题
  • 订阅在发布之后

Solution:

Terminal window
# 1. 验证 Topic 完全匹配(区分大小写)
mosquitto_sub -h localhost -t "home/temperature" -v
# 2. 使用通配符测试
mosquitto_sub -h localhost -t "home/#" -v
# 3. 先订阅,后发布
# 终端 1:
mosquitto_sub -h localhost -t "test/topic"
# 终端 2:
mosquitto_pub -h localhost -t "test/topic" -m "test message"
  • 推荐: 使用层级化的 Topic 结构(如 building/floor/room/sensor_type
  • 推荐: 保持 payload 简洁,优先使用 JSON 格式
  • 推荐: 根据场景选择合适的 QoS 级别
  • 避免: Topic 以斜杠开头(如 /home/temperature
  • 避免: 在 Topic 中使用空格或特殊字符
  • 避免: 过度复杂的 Topic 层级(建议不超过 5 层)

本节要点总结:

  1. MQTT 是轻量级的发布-订阅协议

    • 专为低带宽、高延迟、不可靠网络设计
    • 1999 年由 IBM 开发
    • 已成为 IoT 领域最广泛使用的协议
  2. 核心架构包含三个组件

    • Publisher:发布消息
    • Broker:路由和分发消息
    • Subscriber:接收消息
  3. 关键术语

    • Topic:消息的目标地址(层级结构)
    • Payload:消息内容
    • QoS:消息传递可靠性级别
    • Retained Message:Broker 保留的最后一条消息
  4. MQTT 的优势

    • 轻量级(最小 2 字节消息头)
    • 支持一对多通信
    • 多平台、多语言支持
    • 开源生态完善