1. 物联网与MQTT协议概述

各位同学好,我是你们这期课程的讲师。咱们今天正式开篇,聊聊物联网和MQTT协议。说实话,我做了十几年嵌入式开发,从最早的8051单片机一路做到现在的ESP32,感触最深的就是通信协议的变化。以前设备之间通信,串口、I2C、SPI这些板级协议就够用了。但到了物联网时代,设备要上云,要远程控制,传统的协议就有点力不从心了。

MQTT正是在这个背景下诞生的。它轻量、省带宽、支持低带宽和不稳定网络,特别适合资源受限的嵌入式设备。我个人习惯把MQTT比作物联网世界的“信使”——它不关心你传的是什么数据,只负责把数据可靠地送到目的地。

1.1 物联网架构简介

先看一张图,了解一下物联网的整体架构。这样你后面学MQTT时,就知道它处在哪个位置了。

物联网四层架构(从下到上):

  • 感知层:传感器、执行器、RFID标签等。负责采集数据和执行命令。
  • 网络层:Wi-Fi、LoRa、NB-IoT、4G/5G等。负责数据传输。
  • 平台层:云平台(如阿里云IoT、AWS IoT)、MQTT Broker。负责设备管理、数据存储、规则引擎。
  • 应用层:手机App、Web仪表盘、业务系统。负责数据展示和业务逻辑。

MQTT协议主要工作在网络层和平台层之间。它不关心底层是Wi-Fi还是4G,只负责把应用层的数据打包成标准格式,通过TCP/IP传输。

物联网四层架构与MQTT位置 应用层 手机App · Web仪表盘 · 业务系统 平台层 云平台 · MQTT Broker · 规则引擎 ← MQTT协议在此 → 网络层 Wi-Fi · LoRa · NB-IoT · 4G/5G 感知层 传感器 · 执行器 · RFID · 嵌入式设备

我的经验:很多初学者容易把MQTT和HTTP混为一谈。其实它们分工不同——HTTP是“请求-响应”模式,适合浏览器看网页;MQTT是“发布-订阅”模式,适合设备之间实时通信。你想想看,如果每个传感器都像HTTP那样频繁建立连接,那带宽和电量根本扛不住。

1.2 MQTT协议诞生背景

MQTT全称是Message Queuing Telemetry Transport(消息队列遥测传输)。它最早是IBM在1999年开发的,目的是用于石油管道监控。那时候卫星通信带宽极低,一个数据包可能只有几十字节,传统的HTTP头就有几百字节,根本没法用。

我记得2015年第一次接触MQTT时,是在一个智能农业项目里。客户要求用2G网络传输土壤湿度数据,每5分钟上报一次。如果用HTTP,光TCP三次握手就要消耗大量流量,而且2G网络延迟高、不稳定。后来换成MQTT,流量直接降了80%,而且断线重连机制让系统稳定了很多。

MQTT后来在2014年成为OASIS标准,2016年发布MQTT 5.0版本。现在几乎所有主流云平台都支持MQTT,包括阿里云、华为云、AWS、Azure。

1.3 MQTT vs HTTP vs CoAP

很多同学会问:为什么物联网不用HTTP?CoAP又是什么?我整理了一张对比表,你看完就明白了。

特性 MQTT HTTP CoAP
通信模型 发布/订阅 请求/响应 请求/响应 + 观察者
传输层 TCP TCP UDP
报文开销 最小2字节 几百字节 4字节
QoS支持 3级(0/1/2) 无原生QoS 确认/非确认
实时性 高(长连接推送) 低(轮询) 中
适用场景 传感器、远程监控、推送 Web页面、REST API 极低功耗设备、受限网络

避坑指南:我曾经在一个项目中,用HTTP轮询方式采集100个传感器的数据。结果服务器压力巨大,而且传感器电池两天就没电了。后来换成MQTT,电池续航直接提升到3个月。所以选协议时,一定要考虑功耗和网络开销。

说白了,HTTP是为“人看网页”设计的,MQTT是为“机器对话”设计的。CoAP虽然更轻量,但基于UDP,可靠性不如MQTT。我个人习惯:如果设备有Wi-Fi或以太网,优先用MQTT;如果设备是电池供电且网络极差,可以考虑CoAP。

1.4 MQTT核心特性

MQTT有三大核心特性:发布/订阅模型、QoS等级、遗嘱消息。这三个特性是MQTT的灵魂,也是你后面写代码时必须理解的内容。

1.4.1 发布/订阅模型

传统HTTP是“客户端-服务器”模式,客户端主动请求,服务器被动响应。MQTT不一样,它引入了Broker(代理)的概念。

  • 发布者(Publisher):发送消息到某个主题(Topic)。比如温度传感器发布数据到 sensor/temperature。
  • 订阅者(Subscriber):订阅感兴趣的主题。比如手机App订阅 sensor/temperature,就能收到温度数据。
  • Broker:负责接收发布者的消息,并转发给所有订阅者。

这样做的好处是:发布者和订阅者完全解耦。发布者不需要知道谁在订阅,订阅者也不需要知道谁在发布。你想想看,如果100个传感器都要和手机App直连,那连接数就是100×100=10000条。有了Broker,传感器只连Broker,App也只连Broker,连接数降到200条。

MQTT 发布/订阅模型 MQTT Broker 消息路由 · 会话管理 发布者 温度传感器 发布者 湿度传感器 订阅者 手机App 订阅者 Web仪表盘 发布: sensor/temp 发布: sensor/humid 订阅: sensor/# 订阅: sensor/#

1.4.2 QoS等级

QoS(Quality of Service)是MQTT保证消息可靠性的机制。它有三个等级:

等级 名称 发送次数 可靠性 适用场景
QoS 0 至多一次 1次(不确认) 最低 传感器高频数据(如温度),丢一帧无所谓
QoS 1 至少一次 至少1次(确认重传) 中等 控制指令(如开灯),允许重复
QoS 2 恰好一次 4次握手 最高 计费、支付等关键数据

我的建议:在ESP32项目中,大部分场景用QoS 0或QoS 1就够了。QoS 2虽然可靠,但开销大、延迟高。我曾经在一个智能门锁项目里用了QoS 2,结果因为网络抖动,消息重传导致门锁响应延迟了3秒。后来改成QoS 1,配合业务层的去重逻辑,效果反而更好。

1.4.3 遗嘱消息

遗嘱消息(Will Message)是MQTT一个非常实用的特性。它允许客户端在连接Broker时,预先设置一条“遗言”。如果客户端异常断开(比如掉电、断网),Broker会自动帮它发布这条遗言。

举个例子:你有一个烟雾报警器,它正常时每隔10秒上报一次“一切正常”。如果它突然掉线了,Broker就会发布遗嘱消息“设备离线,可能发生火灾”。其他订阅者收到这条消息后,可以立即触发报警。

避坑指南:我曾经在一个项目中忘了设置遗嘱消息,结果设备掉线后,服务器一直以为设备还在线。直到用户投诉说设备没反应,我才发现设备早就离线了。从那以后,我每个项目都会加上遗嘱消息,哪怕只是简单的“设备离线”通知。

遗嘱消息的配置很简单,在连接Broker时设置三个参数:

// 伪代码示例
client.connect({
  willTopic: "device/status",      // 遗嘱主题
  willPayload: "offline",          // 遗嘱内容
  willQoS: 1,                      // 遗嘱QoS
  willRetain: true                 // 是否保留
});