MQTT
MQTT是Message Queuing Telemetry Transport(消息队列遥测传输)的缩写,是一种轻量级的、基于发布/订阅模式的消息通信协议,最初是由IBM公司在20世纪90年代开发的。MQTT协议专门应用于物联网设备之间的通信,旨在实现物联网设备的低带宽、低功耗和低成本特性。MQTT协议采用客户端/服务器模式,其中客户端可以是传感器、智能设备、移动应用程序等,而服务器则可以是云端服务器或物联网网关。MQTT协议的核心概念是主题(Topic)和消息(Message),客户端可以发布消息到一个或多个主题,也可以订阅一个或多个主题以接收消息。MQTT协议的优点包括:具有低带宽和低功耗特性,适用于各种物联网设备;支持高度灵活的主题订阅机制,可以实现高效的消息传输;支持多种消息质量等级,可以满足不同的应用需求;支持TLS加密和认证机制,可以提高消息传输的安全性。MQTT协议已经被广泛应用于各种物联网场景,如智能家居、智能交通、智能医疗和智能制造等。

查看更多相关内容
MQTT 的主题通配符有哪些?如何使用?MQTT 的主题通配符是一种强大的订阅机制,允许客户端订阅一类主题而不是单个主题,提高了订阅的灵活性。
## 主题通配符类型
MQTT 提供两种通配符:
### 1. 单级通配符(+)
- **符号**:加号(+)
- **作用**:匹配主题中的单个层级
- **位置**:可以出现在主题的任何位置
- **限制**:不能匹配空层级
### 2. 多级通配符(#)
- **符号**:井号(#)
- **作用**:匹配主题中的多个层级(包括零个)
- **位置**:必须出现在主题的最后
- **限制**:必须是主题过滤器的最后一个字符
## 通配符使用示例
### 单级通配符(+)示例
```
订阅主题:home/+/temperature
匹配的主题:
- home/livingroom/temperature ✓
- home/bedroom/temperature ✓
- home/kitchen/temperature ✓
不匹配的主题:
- home/livingroom/kitchen/temperature ✗(层级过多)
- home/temperature ✗(层级过少)
- home/livingroom/humidity ✗(最后一层不匹配)
```
```
订阅主题:sensor/+/data/+
匹配的主题:
- sensor/001/data/temperature ✓
- sensor/002/data/humidity ✓
- sensor/003/data/pressure ✓
不匹配的主题:
- sensor/001/data ✗(层级过少)
- sensor/001/data/temperature/value ✗(层级过多)
```
### 多级通配符(#)示例
```
订阅主题:home/#
匹配的主题:
- home/ ✓
- home/livingroom ✓
- home/livingroom/temperature ✓
- home/livingroom/temperature/value ✓
- home/bedroom/humidity ✓
不匹配的主题:
- home ✗(必须以 / 结尾或包含 /)
- office/livingroom ✗(第一层不匹配)
```
```
订阅主题:sensor/+/#
匹配的主题:
- sensor/001/ ✓
- sensor/001/data ✓
- sensor/001/data/temperature ✓
- sensor/002/data/humidity/value ✓
不匹配的主题:
- sensor ✗(层级过少)
- office/001/data ✗(第一层不匹配)
```
### 组合使用示例
```
订阅主题:home/+/sensors/#
匹配的主题:
- home/livingroom/sensors/ ✓
- home/livingroom/sensors/temperature ✓
- home/livingroom/sensors/temperature/value ✓
- home/bedroom/sensors/humidity ✓
不匹配的主题:
- home/sensors/ ✗(缺少中间层级)
- home/livingroom/sensors ✗(# 必须在最后)
```
## 通配符规则
### 单级通配符(+)规则
1. **匹配单个层级**:只能匹配一个非空层级
2. **可以多次使用**:可以在主题过滤器中多次出现
3. **可以出现在任何位置**:可以在主题的任何层级使用
4. **不能跨层级**:不能匹配多个层级
### 多级通配符(#)规则
1. **匹配多个层级**:可以匹配零个或多个层级
2. **必须在最后**:必须是主题过滤器的最后一个字符
3. **只能使用一次**:每个主题过滤器中只能使用一次
4. **必须跟随 /**:如果主题有多个层级,# 前面必须有 /
## 通配符应用场景
### 1. 设备分类监控
```
场景:监控所有温度传感器
订阅主题:sensors/+/temperature
效果:接收所有设备的温度数据
```
### 2. 区域监控
```
场景:监控某个区域的所有数据
订阅主题:building/floor1/#
效果:接收一楼所有设备的数据
```
### 3. 设备状态监控
```
场景:监控所有设备的在线状态
订阅主题:device/+/status
效果:接收所有设备的状态更新
```
### 4. 数据类型订阅
```
场景:订阅所有告警消息
订阅主题:alert/#
效果:接收所有类型的告警
```
### 5. 分层订阅
```
场景:订阅特定类型的所有子主题
订阅主题:system/metrics/+/#
效果:接收所有系统指标的详细数据
```
## 通配符限制和注意事项
### 1. 发布限制
- **不能发布到通配符主题**:通配符只能用于订阅,不能用于发布
- **主题必须明确**:发布时必须指定完整的主题路径
### 2. 订阅限制
- **通配符不能用于主题层级内部**:如 `home/room+/temperature` 是无效的
- **# 必须在最后**:`home/#/temperature` 是无效的
- **+ 不能匹配空**:`home/+/temperature` 不能匹配 `home//temperature`
### 3. 性能考虑
- **通配符订阅会增加 Broker 负担**:Broker 需要进行主题匹配
- **避免过度使用通配符**:过多的通配符订阅可能影响性能
- **合理设计主题结构**:良好的主题设计可以减少通配符使用
### 4. 安全考虑
- **ACL 权限控制**:通配符订阅需要相应的权限
- **避免过度授权**:通配符订阅可能暴露过多数据
- **最小权限原则**:只授予必要的通配符权限
## 代码示例
### Python (paho-mqtt)
```python
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
# 单级通配符订阅
client.subscribe("sensor/+/temperature")
# 多级通配符订阅
client.subscribe("home/bedroom/#")
# 组合通配符订阅
client.subscribe("system/+/metrics/#")
def on_message(client, userdata, msg):
print(f"Received: {msg.topic} - {msg.payload.decode()}")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.example.com", 1883, 60)
client.loop_forever()
```
### JavaScript (MQTT.js)
```javascript
const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://broker.example.com');
client.on('connect', () => {
console.log('Connected');
// 单级通配符订阅
client.subscribe('sensor/+/temperature');
// 多级通配符订阅
client.subscribe('home/bedroom/#');
// 组合通配符订阅
client.subscribe('system/+/metrics/#');
});
client.on('message', (topic, message) => {
console.log(`Received: ${topic} - ${message.toString()}`);
});
```
## 最佳实践
### 1. 主题设计
- **层级清晰**:主题层级应该清晰、有意义
- **避免过深**:主题层级不宜过深(建议不超过 5 层)
- **使用分隔符**:统一使用 / 作为分隔符
- **命名规范**:使用一致的命名规范
### 2. 通配符使用
- **按需使用**:只在需要时使用通配符
- **避免过度通配**:避免使用过于宽泛的通配符(如 #)
- **组合使用**:合理组合单级和多级通配符
- **性能优化**:在高性能场景下减少通配符使用
### 3. 订阅管理
- **及时取消订阅**:不再需要的订阅应该及时取消
- **避免重复订阅**:避免重复订阅相同的主题
- **监控订阅数量**:监控订阅数量,避免过多订阅
### 4. 安全管理
- **权限控制**:为通配符订阅设置适当的权限
- **最小权限**:只授予必要的最小权限
- **定期审查**:定期审查通配符订阅权限
## 通配符性能优化
### 1. Broker 优化
- **选择合适的 Broker**:选择支持高效通配符匹配的 Broker
- **配置优化**:根据实际需求调整 Broker 配置
- **集群部署**:大规模场景下使用集群部署
### 2. 订阅优化
- **精确订阅优先**:优先使用精确主题订阅
- **减少通配符层级**:减少通配符匹配的层级
- **批量订阅**:使用批量订阅减少连接开销
### 3. 主题优化
- **主题前缀**:使用主题前缀减少匹配范围
- **主题分组**:合理分组主题,减少通配符使用
- **避免通配符嵌套**:避免复杂的通配符嵌套
MQTT 主题通配符是提高订阅灵活性的重要机制,合理使用可以简化应用逻辑,提高开发效率。但需要注意性能和安全问题,避免过度使用通配符。
服务端 · 2月21日 15:45
MQTT 和 HTTP 协议有什么区别?分别在什么场景下使用?MQTT 与 HTTP 是两种常用的网络协议,它们在设计理念、应用场景和技术特点上有显著差异。
## 设计理念对比
### MQTT
- **设计目标**:轻量级、低带宽、低功耗的消息传输协议
- **通信模式**:发布/订阅模式,一对多通信
- **连接方式**:长连接,保持持久连接
- **传输方向**:双向通信,服务器可以主动推送消息
- **协议栈**:应用层协议,基于 TCP
### HTTP
- **设计目标**:请求/响应模式的数据传输协议
- **通信模式**:客户端-服务器模式,一对一通信
- **连接方式**:短连接(HTTP/1.0)或长连接(HTTP/1.1 Keep-Alive)
- **传输方向**:单向通信,客户端主动请求
- **协议栈**:应用层协议,基于 TCP
## 技术特点对比
### 1. 消息传输
| 特性 | MQTT | HTTP |
|-----|------|------|
| 传输模式 | 发布/订阅 | 请求/响应 |
| 消息方向 | 双向 | 单向(客户端→服务器) |
| 实时性 | 高 | 低(需要轮询或 WebSocket) |
| 消息大小 | 小(头部最小 2 字节) | 大(头部通常几百字节) |
| 带宽消耗 | 低 | 高 |
### 2. 连接管理
| 特性 | MQTT | HTTP |
|-----|------|------|
| 连接类型 | 长连接 | 短连接/长连接 |
| 连接保持 | Keep Alive 机制 | Keep-Alive(HTTP/1.1+) |
| 断线重连 | 自动重连 | 需要应用层处理 |
| 心跳机制 | 内置 PING/PONG | 无(需应用层实现) |
### 3. 服务质量(QoS)
| 特性 | MQTT | HTTP |
|-----|------|------|
| QoS 级别 | 3 级(0/1/2) | 无(依赖 TCP) |
| 消息确认 | 支持(PUBACK/PUBREC/PUBCOMP) | 无(依赖 TCP ACK) |
| 消息重传 | 支持 | 无(依赖 TCP 重传) |
| 消息顺序 | 保证 | 保证(TCP) |
### 4. 安全性
| 特性 | MQTT | HTTP |
|-----|------|------|
| 加密支持 | TLS/SSL(端口 8883) | HTTPS(端口 443) |
| 认证方式 | 用户名/密码、证书、Token | Basic Auth、Digest、OAuth |
| 访问控制 | ACL(主题级别) | 基于路径、权限系统 |
| 数据完整性 | 保证 | 保证 |
## 性能对比
### 1. 资源消耗
| 指标 | MQTT | HTTP |
|-----|------|------|
| CPU 占用 | 低 | 中等 |
| 内存占用 | 低 | 中等 |
| 网络带宽 | 低 | 高 |
| 电池消耗 | 低 | 高 |
| 数据包大小 | 小 | 大 |
### 2. 并发能力
| 指标 | MQTT | HTTP |
|-----|------|------|
| 单连接消息数 | 高 | 低 |
| 并发连接数 | 高(百万级) | 中等(万级) |
| 消息吞吐量 | 高 | 中等 |
| 延迟 | 低(毫秒级) | 中等(百毫秒级) |
## 应用场景对比
### MQTT 适用场景
1. **物联网设备**
- 传感器数据采集
- 智能家居控制
- 工业自动化
- 车联网
2. **实时通信**
- 即时消息
- 实时监控
- 在线游戏
- 聊天应用
3. **推送通知**
- 移动应用推送
- 消息通知
- 警报系统
### HTTP 适用场景
1. **Web 应用**
- 网页浏览
- API 调用
- 文件下载
- 表单提交
2. **数据传输**
- RESTful API
- 文件上传/下载
- 大数据传输
- 媒体流
3. **企业应用**
- 企业系统集成
- 微服务通信
- 数据同步
- 业务流程
## 代码示例对比
### MQTT 消息发布
```python
import paho.mqtt.client as mqtt
client = mqtt.Client()
client.connect("broker.example.com", 1883)
client.publish("sensor/temperature", "25.5")
client.disconnect()
```
### HTTP 请求
```python
import requests
response = requests.post(
"https://api.example.com/sensor/temperature",
json={"value": 25.5}
)
print(response.status_code)
```
## 优缺点总结
### MQTT 优点
- 轻量级,适合资源受限设备
- 低带宽,低功耗
- 实时性好,支持双向通信
- 支持一对多消息分发
- 内置 QoS 保证
- 适合物联网场景
### MQTT 缺点
- 不适合大数据传输
- 不适合文件传输
- 不适合复杂查询
- 生态系统相对较小
### HTTP 优点
- 通用性强,生态丰富
- 支持大数据传输
- 支持复杂查询
- 标准化程度高
- 易于调试和监控
- 支持缓存
### HTTP 缺点
- 头部开销大
- 实时性差(需要轮询)
- 不适合低带宽环境
- 服务器不能主动推送
- 资源消耗较高
## 选择建议
### 选择 MQTT 的情况
- 需要实时双向通信
- 设备资源受限(低带宽、低功耗)
- 需要一对多消息分发
- 物联网应用
- 需要离线消息支持
- 网络不稳定环境
### 选择 HTTP 的情况
- 需要传输大数据
- 需要复杂查询和过滤
- Web 应用开发
- RESTful API 设计
- 需要广泛的工具支持
- 需要缓存机制
## 混合使用
在实际应用中,可以结合使用 MQTT 和 HTTP:
- **MQTT**:用于实时数据传输、设备控制、状态更新
- **HTTP**:用于配置管理、数据查询、文件传输、API 访问
例如:
- 传感器数据通过 MQTT 实时上报
- 历史数据查询通过 HTTP API
- 设备配置通过 HTTP RESTful API
- 告警通知通过 MQTT 实时推送
MQTT 和 HTTP 各有优势,根据具体应用场景选择合适的协议,或者结合使用以发挥各自优势。
服务端 · 2月21日 15:45
MQTT Broker 的主要功能有哪些?常用的 MQTT Broker 实现有哪些?MQTT Broker 是 MQTT 协议的核心组件,负责消息的接收、路由和分发。以下是 MQTT Broker 的主要功能和常用实现。
## Broker 的核心功能
### 1. 连接管理
- **客户端连接**:接受和处理来自客户端的连接请求
- **认证授权**:验证客户端身份,控制访问权限
- **会话管理**:维护客户端会话状态
- **心跳检测**:通过 Keep Alive 机制检测客户端存活状态
### 2. 消息路由
- **主题匹配**:根据订阅关系匹配消息主题
- **消息分发**:将消息转发给订阅该主题的所有客户端
- **QoS 处理**:确保消息按照指定的 QoS 级别传递
- **消息过滤**:支持基于主题和内容的消息过滤
### 3. 持久化存储
- **离线消息**:存储离线客户端的订阅消息
- **消息队列**:临时存储待分发的消息
- **会话状态**:保存客户端的订阅关系和未确认消息
- **消息日志**:记录消息传输历史
### 4. 安全机制
- **TLS/SSL 加密**:保护数据传输安全
- **用户认证**:支持用户名/密码、证书等多种认证方式
- **访问控制**:基于主题和客户端的权限管理
- **ACL(访问控制列表)**:细粒度的权限控制
### 5. 性能优化
- **消息压缩**:减少网络传输开销
- **批量处理**:提高消息处理效率
- **负载均衡**:支持集群部署,分散请求压力
- **连接池**:复用网络连接,降低资源消耗
## 常用 MQTT Broker 实现
### 1. Mosquitto
- **特点**:轻量级、开源、易于部署
- **语言**:C 语言实现
- **适用场景**:嵌入式设备、小型项目
- **优点**:
- 资源占用少
- 配置简单
- 社区活跃
- **缺点**:
- 性能相对较低
- 企业级功能有限
### 2. EMQX
- **特点**:高性能、分布式、企业级
- **语言**:Erlang/OTP 实现
- **适用场景**:大规模物联网平台、企业应用
- **优点**:
- 支持百万级并发连接
- 内置规则引擎
- 丰富的管理界面
- 支持集群和负载均衡
- **缺点**:
- 学习曲线较陡
- 资源占用较高
### 3. HiveMQ
- **特点**:商业级、高性能、可扩展
- **语言**:Java 实现
- **适用场景**:企业级应用、金融、医疗
- **优点**:
- 高性能和稳定性
- 企业级支持和服务
- 丰富的插件生态
- **缺点**:
- 商业版本收费
- 资源占用较高
### 4. VerneMQ
- **特点**:高性能、分布式、可扩展
- **语言**:Erlang 实现
- **适用场景**:大规模实时通信
- **优点**:
- 高并发支持
- 灵活的插件系统
- 支持集群部署
- **缺点**:
- 文档相对较少
- 社区规模较小
### 5. RabbitMQ(MQTT 插件)
- **特点**:多功能消息代理
- **语言**:Erlang 实现
- **适用场景**:需要多种协议支持的系统
- **优点**:
- 支持多种协议(AMQP、MQTT、STOMP)
- 成熟稳定
- 丰富的管理工具
- **缺点**:
- MQTT 功能相对基础
- 性能不如专用 Broker
## Broker 选择建议
### 小型项目/原型开发
- **推荐**:Mosquitto
- **理由**:轻量、简单、免费
### 中型项目/企业应用
- **推荐**:EMQX 社区版
- **理由**:功能丰富、性能良好、免费
### 大规模物联网平台
- **推荐**:EMQX 企业版或 HiveMQ
- **理由**:高性能、企业级支持、可扩展
### 需要多协议支持
- **推荐**:RabbitMQ
- **理由**:协议支持全面、成熟稳定
## 性能指标对比
| Broker | 并发连接数 | 消息吞吐量 | 资源占用 | 部署复杂度 |
|--------|-----------|-----------|---------|-----------|
| Mosquitto | 1万+ | 10万+ | 低 | 简单 |
| EMQX | 100万+ | 100万+ | 中 | 中等 |
| HiveMQ | 100万+ | 100万+ | 高 | 中等 |
| VerneMQ | 100万+ | 100万+ | 中 | 中等 |
| RabbitMQ | 10万+ | 10万+ | 中 | 中等 |
选择 MQTT Broker 时,需要综合考虑项目规模、性能要求、预算和技术团队能力等因素。
服务端 · 2月21日 15:45
MQTT 5.0 相比 MQTT 3.1.1 有哪些新特性?MQTT 5.0 版本在 3.1.1 版本的基础上进行了重大改进,引入了许多新特性,显著提升了协议的功能性和灵活性。
## MQTT 5.0 主要新特性
### 1. 属性(Properties)
- **定义**:在控制报文中携带键值对形式的元数据
- **作用**:扩展协议功能,无需修改协议格式
- **应用场景**:
- 消息过期时间
- 请求/响应模式
- 订阅标识符
- 内容类型
- 用户属性(自定义元数据)
### 2. 请求/响应模式(Request/Response Pattern)
- **相关属性**:
- `Response Topic`:指定响应消息的主题
- `Correlation Data`:关联请求和响应
- **工作流程**:
1. 客户端发送请求消息,包含 Response Topic 和 Correlation Data
2. 服务端处理请求
3. 服务端发送响应消息到 Response Topic,包含相同的 Correlation Data
4. 客户端根据 Correlation Data 匹配响应
- **优势**:
- 简化应用层实现
- 减少自定义协议开发
- 提高互操作性
### 3. 会话和消息过期
- **会话过期**:
- `Session Expiry Interval`:指定会话过期时间(秒)
- 0 表示立即过期,4294967295 表示永不过期
- 替代了 Clean Session 标志
- **消息过期**:
- `Message Expiry Interval`:指定消息过期时间(秒)
- Broker 不再分发过期消息
- 减少无效消息传输
- **优势**:
- 更灵活的会话管理
- 自动清理过期资源
- 减少存储压力
### 4. 共享订阅(Shared Subscriptions)
- **语法**:`$share/<group>/<topic>`
- **示例**:`$share/consumer1/sensor/data`
- **工作原理**:
- 多个订阅者组成一个共享组
- 每条消息只分发给组中的一个订阅者
- 实现负载均衡
- **优势**:
- 提高消息处理能力
- 实现消费者扩展
- 避免消息重复处理
- **应用场景**:
- 高吞吐量数据处理
- 分布式任务处理
- 微服务架构
### 5. 订阅标识符(Subscription Identifier)
- **定义**:为订阅分配一个数字标识符
- **特点**:
- 每个客户端可以有多个订阅标识符
- 标识符范围:1-268435455
- 在 PUBLISH 报文中返回匹配的订阅标识符
- **应用场景**:
- 区分不同的订阅
- 实现复杂的消息路由
- 简化应用逻辑
### 6. 主题别名(Topic Alias)
- **定义**:用数字代替完整的主题字符串
- **机制**:
- 客户端和 Broker 独立维护别名映射
- 别名范围:1-65535
- 在 CONNECT 或 PUBLISH 中声明
- **优势**:
- 减少网络传输量
- 降低带宽消耗
- 提高传输效率
- **应用场景**:
- 长主题名称
- 高频消息传输
- 带宽受限环境
### 7. 流量控制(Flow Control)
- **接收最大值(Receive Maximum)**:
- 客户端指定未确认 PUBLISH 报文的最大数量
- 防止消息积压
- 默认值:65535
- **最大数据包大小(Maximum Packet Size)**:
- 限制最大数据包大小
- 防止大包攻击
- 默认值:无限制
- **优势**:
- 防止资源耗尽
- 提高系统稳定性
- 适应不同网络条件
### 8. 原因码(Reason Codes)
- **定义**:更详细的错误和状态信息
- **范围**:0x00-0xFF
- **分类**:
- 成功码(0x00-0x00)
- 错误码(0x80-0xFF)
- **优势**:
- 更精确的错误诊断
- 更好的问题排查
- 改进的互操作性
### 9. 认证增强(Enhanced Authentication)
- **认证方法(Authentication Method)**:
- 指定认证方法(如 SCRAM)
- 支持多种认证协议
- **认证数据(Authentication Data)**:
- 携带认证相关的数据
- 支持多轮认证
- **重新认证(Re-authentication)**:
- 在连接期间重新认证
- 无需断开连接
- **优势**:
- 更灵活的认证机制
- 支持现代认证协议
- 提高安全性
### 10. 服务器断开(Server Disconnect)
- **功能**:服务器主动断开客户端连接
- **原因码**:说明断开原因
- **服务器引用**:提供服务器信息
- **应用场景**:
- 服务器维护
- 强制下线
- 负载均衡
## MQTT 3.1.1 vs MQTT 5.0 对比
| 特性 | MQTT 3.1.1 | MQTT 5.0 |
|-----|-----------|----------|
| 属性支持 | 无 | 支持 |
| 请求/响应 | 自定义实现 | 原生支持 |
| 会话管理 | Clean Session | Session Expiry |
| 共享订阅 | Broker 扩展 | 标准特性 |
| 主题别名 | 无 | 支持 |
| 流量控制 | 无 | 支持 |
| 错误码 | 简单 | 详细 |
| 认证机制 | 基础 | 增强 |
| 消息过期 | 无 | 支持 |
| 服务器断开 | 无 | 支持 |
## 迁移建议
### 向后兼容性
- MQTT 5.0 客户端可以连接到 MQTT 3.1.1 Broker
- MQTT 3.1.1 客户端可以连接到 MQTT 5.0 Broker
- 新特性仅在双方都支持时生效
### 迁移策略
1. **评估需求**:确定是否需要新特性
2. **逐步迁移**:先升级 Broker,再升级客户端
3. **测试验证**:充分测试兼容性和功能
4. **监控观察**:监控迁移后的系统表现
## 应用场景
### 适合使用 MQTT 5.0 的场景
- 需要请求/响应模式的应用
- 高并发、高吞吐量的物联网平台
- 需要精确错误诊断的系统
- 需要灵活认证机制的企业应用
- 带宽受限的物联网设备
### 可以继续使用 MQTT 3.1.1 的场景
- 简单的传感器数据采集
- 低频率的消息传输
- 已有稳定运行的系统
- 资源极度受限的设备
MQTT 5.0 的引入显著提升了协议的功能性和灵活性,为更复杂的物联网应用提供了更好的支持。
服务端 · 2月21日 15:45
MQTT 的遗嘱消息(Last Will)是什么?如何使用?MQTT 的遗嘱消息(Last Will and Testament,LWT)是一种重要的机制,用于在客户端异常断开连接时通知其他客户端。
## 遗嘱消息的概念
### 定义
遗嘱消息是客户端在连接时预先设置的一条消息,当客户端异常断开连接时,Broker 会自动将这条消息发布到指定的主题。
### 作用
- **异常检测**:通知其他客户端某个设备已离线
- **状态通知**:发布设备离线状态
- **故障告警**:触发告警机制
- **资源清理**:通知系统清理相关资源
## 遗嘱消息的工作原理
### 设置遗嘱消息
客户端在发送 CONNECT 报文时设置遗嘱消息参数:
```
CONNECT 报文参数:
- Will Flag: true(启用遗嘱消息)
- Will Topic: 遗嘱消息的主题
- Will Message: 遗嘱消息的内容
- Will QoS: 遗嘱消息的 QoS 级别
- Will Retain: 是否保留遗嘱消息
```
### 触发条件
遗嘱消息在以下情况下会被触发:
1. **客户端异常断开**
- 网络故障
- 设备断电
- 程序崩溃
- 连接超时
2. **Broker 检测到连接断开**
- Keep Alive 超时
- TCP 连接断开
- 心跳检测失败
### 不触发的情况
以下情况不会触发遗嘱消息:
1. **正常断开连接**
- 客户端发送 DISCONNECT 报文
- 正常关闭连接
2. **连接未建立**
- CONNECT 报文发送失败
- 连接被拒绝
## 遗嘱消息的参数
### Will Flag(遗嘱标志)
- **作用**:标识是否启用遗嘱消息
- **值**:true/false
- **必需**:启用遗嘱消息时必须为 true
### Will Topic(遗嘱主题)
- **作用**:指定遗嘱消息发布的主题
- **格式**:标准的 MQTT 主题字符串
- **示例**:`device/123/status`
- **要求**:必须设置
### Will Message(遗嘱消息内容)
- **作用**:遗嘱消息的实际内容
- **格式**:二进制数据
- **示例**:`offline` 或 `{"status":"offline","timestamp":1234567890}`
- **要求**:必须设置
### Will QoS(遗嘱 QoS)
- **作用**:指定遗嘱消息的 QoS 级别
- **值**:0/1/2
- **默认值**:0
- **选择建议**:
- QoS 0:一般状态通知
- QoS 1:重要状态通知
- QoS 2:关键状态通知
### Will Retain(遗嘱保留)
- **作用**:指定是否保留遗嘱消息
- **值**:true/false
- **默认值**:false
- **影响**:
- true:新订阅者会收到遗嘱消息
- false:只有在线订阅者收到遗嘱消息
## 使用场景
### 1. 设备在线状态监控
```
设备上线:
- 发布 "online" 到 device/123/status
设备离线(正常):
- 发布 "offline" 到 device/123/status
设备离线(异常):
- 遗嘱消息 "offline" 发布到 device/123/status
```
### 2. 故障告警
```
遗嘱主题:alert/device/123
遗嘱消息:{"type":"offline","device":"123","timestamp":1234567890}
监控系统订阅 alert/device/123
收到遗嘱消息后触发告警
```
### 3. 资源清理
```
遗嘱主题:cleanup/device/123
遗嘱消息:{"device":"123","action":"cleanup"}
清理服务订阅 cleanup/device/123
收到遗嘱消息后清理相关资源
```
### 4. 负载均衡
```
遗嘱主题:worker/offline
遗嘱消息:{"worker":"worker1"}
负载均衡器订阅 worker/offline
收到遗嘱消息后重新分配任务
```
## 代码示例
### Python (paho-mqtt)
```python
import paho.mqtt.client as mqtt
import json
import time
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
client.subscribe("device/+/status")
def on_message(client, userdata, msg):
print(f"Received: {msg.topic} - {msg.payload.decode()}")
client = mqtt.Client()
# 设置遗嘱消息
will_topic = "device/123/status"
will_message = json.dumps({"status": "offline", "timestamp": int(time.time())})
client.will_set(will_topic, will_message, qos=1, retain=True)
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.example.com", 1883, 60)
# 发布在线状态
client.publish("device/123/status", json.dumps({"status": "online"}))
client.loop_forever()
```
### JavaScript (MQTT.js)
```javascript
const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://broker.example.com', {
will: {
topic: 'device/123/status',
payload: JSON.stringify({ status: 'offline', timestamp: Date.now() }),
qos: 1,
retain: true
}
});
client.on('connect', () => {
console.log('Connected');
// 发布在线状态
client.publish('device/123/status', JSON.stringify({ status: 'online' }));
// 订阅状态主题
client.subscribe('device/+/status');
});
client.on('message', (topic, message) => {
console.log(`Received: ${topic} - ${message.toString()}`);
});
```
## 最佳实践
### 1. 遗嘱消息设计
- **简洁明了**:消息内容简洁,易于解析
- **包含时间戳**:便于追踪离线时间
- **设备标识**:明确标识是哪个设备
- **状态信息**:包含详细的离线原因
### 2. 主题命名规范
```
推荐格式:
- device/{device_id}/status
- alert/{device_id}/offline
- cleanup/{device_id}
避免使用:
- 通配符作为遗嘱主题
- 过于复杂的主题结构
```
### 3. QoS 选择
- **一般设备**:QoS 0
- **重要设备**:QoS 1
- **关键设备**:QoS 2
### 4. Retain 设置
- **状态监控**:建议设置为 true
- **告警通知**:建议设置为 false
- **资源清理**:根据需求设置
### 5. 遗嘱消息处理
- **及时处理**:收到遗嘱消息后及时处理
- **避免重复**:防止重复处理同一设备的离线事件
- **记录日志**:记录离线事件,便于问题排查
## 注意事项
1. **正常断开**:正常断开连接时,应该先发送 DISCONNECT 报文,避免触发遗嘱消息
2. **遗嘱消息更新**:重新连接时可以更新遗嘱消息内容
3. **Broker 限制**:某些 Broker 可能对遗嘱消息有大小限制
4. **网络延迟**:网络延迟可能导致遗嘱消息延迟发送
5. **多设备场景**:在多设备场景中,需要明确区分不同设备的遗嘱消息
## 遗嘱消息的局限性
1. **无法区分离线原因**:遗嘱消息不包含具体的离线原因
2. **可能误报**:网络抖动可能导致误报
3. **处理延迟**:从离线到发送遗嘱消息可能有延迟
4. **依赖 Broker**:完全依赖 Broker 的可靠性
MQTT 遗嘱消息是物联网应用中非常重要的机制,合理使用可以有效监控设备状态,提高系统的可靠性和可维护性。
服务端 · 2月21日 15:45
MQTT 的发布/订阅模式是如何工作的?MQTT 的发布/订阅模式是一种消息传递架构,它解耦了消息的生产者和消费者,实现了灵活的一对多通信。
## 核心概念
### 1. 主题(Topic)
- **定义**:主题是消息的路由地址,采用层级结构
- **格式**:使用斜杠(/)分隔的字符串,如 `home/livingroom/temperature`
- **特点**:
- 层级清晰,便于组织和管理
- 支持通配符订阅
- 大小写敏感
- 长度限制:最多 65535 字节
### 2. 发布者(Publisher)
- **角色**:消息的生产者
- **功能**:向特定主题发送消息
- **特点**:
- 不需要知道订阅者的存在
- 可以同时向多个主题发布消息
- 发布后立即返回,不等待订阅者响应
### 3. 订阅者(Subscriber)
- **角色**:消息的消费者
- **功能**:订阅感兴趣的主题,接收相关消息
- **特点**:
- 可以订阅多个主题
- 可以使用通配符订阅一类主题
- 只接收订阅后发布的消息
### 4. Broker(代理服务器)
- **角色**:消息的中转站和路由器
- **功能**:
- 接收发布者发送的消息
- 根据订阅关系将消息分发给订阅者
- 管理客户端连接和会话
- 处理消息的 QoS 保证
## 工作流程
1. **连接建立**:客户端(发布者/订阅者)连接到 Broker
2. **订阅主题**:订阅者向 Broker 发送订阅请求
3. **发布消息**:发布者向特定主题发送消息
4. **消息路由**:Broker 接收消息,查找订阅该主题的客户端
5. **消息分发**:Broker 将消息转发给所有订阅者
6. **消息接收**:订阅者接收并处理消息
## 通配符订阅
### 单级通配符(+)
- 匹配单个层级
- 示例:`home/+/temperature` 匹配 `home/livingroom/temperature`,但不匹配 `home/livingroom/kitchen/temperature`
### 多级通配符(#)
- 匹配多个层级,必须放在主题末尾
- 示例:`home/#` 匹配 `home/` 下的所有主题
## 优势
1. **解耦性**:发布者和订阅者完全解耦,互不依赖
2. **灵活性**:支持一对多、多对一、多对多的通信模式
3. **可扩展性**:易于添加新的发布者和订阅者
4. **异步性**:发布者不需要等待订阅者响应
5. **高效性**:Broker 负责消息路由,减少网络开销
## 与点对点模式的对比
| 特性 | 发布/订阅模式 | 点对点模式 |
|-----|-------------|-----------|
| 耦合度 | 低 | 高 |
| 消息接收者 | 多个 | 一个 |
| 消息持久化 | 可选 | 通常需要 |
| 复杂度 | 中等 | 简单 |
| 适用场景 | 广播、通知 | 直接通信 |
MQTT 的发布/订阅模式使其成为物联网、实时通信和消息推送等场景的理想选择。
服务端 · 2月21日 15:45
MQTT 的保留消息(Retained Messages)是什么?如何使用?MQTT 的保留消息(Retained Messages)是一种特殊的消息机制,允许 Broker 保存最新消息,供新订阅者接收。
## 保留消息的概念
### 定义
保留消息是 Broker 持久化存储的消息,当有新的客户端订阅该主题时,Broker 会立即将保留消息发送给该客户端。
### 作用
- **状态同步**:新订阅者可以立即获取最新状态
- **初始化数据**:为新连接的客户端提供初始数据
- **状态恢复**:帮助客户端快速恢复到最新状态
- **减少请求**:避免客户端主动请求最新状态
## 保留消息的工作原理
### 设置保留消息
发布消息时设置 Retain 标志:
```
PUBLISH 报文参数:
- Topic: 主题名称
- Payload: 消息内容
- QoS: QoS 级别
- Retain: true(设置为保留消息)
```
### 保留消息的存储
- **存储位置**:Broker 内存或持久化存储
- **存储数量**:每个主题只保留一条最新消息
- **存储覆盖**:新发布的保留消息会覆盖之前的保留消息
### 保留消息的发送
当客户端订阅主题时:
1. 客户端发送 SUBSCRIBE 报文
2. Broker 检查该主题是否有保留消息
3. 如果有,立即发送保留消息给客户端
4. 然后发送后续的新消息
## 保留消息的特性
### 1. 每个主题一条
- **规则**:每个主题只保留一条最新的保留消息
- **覆盖机制**:新发布的保留消息会替换之前的
- **清除机制**:发布空消息(Payload 为空)可以清除保留消息
### 2. QoS 级别
- **继承性**:保留消息的 QoS 级别由发布时决定
- **订阅限制**:订阅者接收的 QoS 级别受限于订阅时的 QoS 设置
- **QoS 规则**:实际 QoS = min(发布 QoS, 订阅 QoS)
### 3. 持久化
- **内存存储**:默认存储在内存中
- **持久化存储**:可配置持久化到磁盘
- **Broker 重启**:持久化的保留消息在 Broker 重启后仍然存在
### 4. 消息顺序
- **发送顺序**:保留消息在普通消息之前发送
- **订阅时机**:只在订阅时发送一次
- **后续消息**:不重复发送保留消息
## 使用场景
### 1. 设备状态同步
```
场景:温度传感器
保留主题:sensor/123/temperature
保留消息:{"value": 25.5, "unit": "C", "timestamp": 1234567890}
新订阅者订阅 sensor/123/temperature
立即收到最新温度值
```
### 2. 配置信息发布
```
场景:设备配置
保留主题:config/device/123
保留消息:{"mode": "auto", "interval": 60}
新设备上线订阅配置主题
立即获取最新配置
```
### 3. 系统状态广播
```
场景:系统状态
保留主题:system/status
保留消息:{"status": "running", "version": "1.0.0"}
新客户端订阅系统状态
立即获取当前系统状态
```
### 4. 开关状态
```
场景:智能开关
保留主题:switch/123/state
保留消息:{"state": "on"}
新订阅者立即获取开关状态
```
## 代码示例
### Python (paho-mqtt)
```python
import paho.mqtt.client as mqtt
import json
import time
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
# 订阅主题
client.subscribe("sensor/+/temperature")
def on_message(client, userdata, msg):
print(f"Received: {msg.topic} - {msg.payload.decode()}")
print(f"Retained: {msg.retain}")
# 发布保留消息
client = mqtt.Client()
client.connect("broker.example.com", 1883, 60)
# 发布保留消息(retain=True)
message = {"value": 25.5, "unit": "C", "timestamp": int(time.time())}
client.publish("sensor/123/temperature", json.dumps(message), retain=True)
# 清除保留消息(发布空消息)
# client.publish("sensor/123/temperature", "", retain=True)
client.disconnect()
# 订阅者
subscriber = mqtt.Client()
subscriber.on_connect = on_connect
subscriber.on_message = on_message
subscriber.connect("broker.example.com", 1883, 60)
subscriber.loop_forever()
```
### JavaScript (MQTT.js)
```javascript
const mqtt = require('mqtt');
// 发布保留消息
const publisher = mqtt.connect('mqtt://broker.example.com');
publisher.on('connect', () => {
console.log('Publisher connected');
// 发布保留消息(retain: true)
const message = JSON.stringify({
value: 25.5,
unit: 'C',
timestamp: Date.now()
});
publisher.publish('sensor/123/temperature', message, { retain: true });
// 清除保留消息(发布空消息)
// publisher.publish('sensor/123/temperature', '', { retain: true });
publisher.end();
});
// 订阅者
const subscriber = mqtt.connect('mqtt://broker.example.com');
subscriber.on('connect', () => {
console.log('Subscriber connected');
subscriber.subscribe('sensor/+/temperature');
});
subscriber.on('message', (topic, message) => {
console.log(`Received: ${topic} - ${message.toString()}`);
console.log(`Retained: ${message.retain}`);
});
```
## 最佳实践
### 1. 保留消息设计
- **状态信息**:保留消息应该表示当前状态
- **简洁明了**:消息内容简洁,易于解析
- **包含时间戳**:便于判断消息的新旧程度
- **版本控制**:可以包含版本信息
### 2. 主题命名
```
推荐格式:
- sensor/{device_id}/temperature
- config/{device_id}
- status/{system_id}
避免使用:
- 通配符主题(不能发布到通配符主题)
- 过于复杂的主题结构
```
### 3. 消息大小
- **限制大小**:保留消息不宜过大
- **建议大小**:通常小于 1KB
- **Broker 限制**:注意 Broker 对消息大小的限制
### 4. QoS 选择
- **一般状态**:QoS 0
- **重要状态**:QoS 1
- **关键状态**:QoS 2
### 5. 清除机制
- **主动清除**:发布空消息清除保留消息
- **定期清理**:定期检查和清理过期的保留消息
- **生命周期管理**:为保留消息设置合理的生命周期
## 注意事项
1. **内存占用**:保留消息会占用 Broker 内存,大量保留消息可能影响性能
2. **持久化配置**:如果需要保留消息在 Broker 重启后仍然存在,需要配置持久化
3. **消息更新**:频繁更新保留消息会增加 Broker 负担
4. **订阅时机**:保留消息只在订阅时发送,不会重复发送
5. **QoS 限制**:订阅者接收的 QoS 级别受限于订阅时的 QoS 设置
6. **空消息清除**:发布空消息(Payload 为空)可以清除保留消息
## 保留消息 vs 遗嘱消息
| 特性 | 保留消息 | 遗嘱消息 |
|-----|---------|---------|
| 触发时机 | 订阅时 | 异常断开时 |
| 消息来源 | 发布者设置 | 客户端设置 |
| 存储位置 | Broker | Broker |
| 发送对象 | 新订阅者 | 订阅该主题的客户端 |
| 消息数量 | 每主题一条 | 每客户端一条 |
| 清除方式 | 发布空消息 | 正常断开或重新连接 |
## 保留消息的局限性
1. **每主题一条**:每个主题只能保留一条消息,无法保存历史消息
2. **内存占用**:大量保留消息会占用较多内存
3. **实时性**:保留消息可能不是最新的(取决于发布频率)
4. **无历史记录**:无法获取历史状态变化
5. **依赖 Broker**:完全依赖 Broker 的可靠性
MQTT 保留消息是物联网应用中非常重要的机制,合理使用可以有效实现状态同步和初始化,提高用户体验和系统可靠性。
服务端 · 2月21日 15:44
MQTT 协议的核心特点和工作原理是什么?MQTT(Message Queuing Telemetry Transport)是一种轻量级的、基于发布/订阅模式的消息通信协议,专门为物联网设备设计。
## 核心特点
1. **轻量级**:MQTT 协议头部最小仅需 2 字节,非常适合带宽受限的网络环境
2. **发布/订阅模式**:解耦消息生产者和消费者,实现一对多通信
3. **三种 QoS 级别**:确保消息在不同网络条件下的可靠传输
4. **低功耗**:适合电池供电的 IoT 设备
5. **TCP/IP 传输**:基于可靠的 TCP 协议,确保消息有序到达
## 工作原理
MQTT 采用客户端-服务器架构:
- **客户端**:可以是传感器、智能设备、移动应用等,负责发布消息或订阅主题
- **服务器(Broker)**:负责接收、过滤和分发消息
## 消息流程
1. 客户端连接到 Broker
2. 客户端订阅感兴趣的主题
3. 发布者向特定主题发送消息
4. Broker 将消息转发给所有订阅该主题的客户端
## 应用场景
- 物联网设备监控
- 实时数据采集
- 移动应用推送通知
- 智能家居控制
- 工业自动化系统
MQTT 的设计理念是在有限的网络资源下提供可靠的消息传递服务,使其成为 IoT 领域的首选协议之一。
服务端 · 2月21日 15:44
MQTT 协议的安全机制有哪些?如何保证 MQTT 通信的安全性?MQTT 协议提供了多种安全机制来保护消息传输的安全性,包括身份认证、访问控制和数据加密等方面。
## 1. 传输层安全(TLS/SSL)
### TLS 加密
- **作用**:在传输层对数据进行加密,防止中间人攻击
- **协议版本**:支持 TLS 1.2 和 TLS 1.3
- **端口**:
- MQTT over TLS:默认端口 8883
- 标准 MQTT:默认端口 1883(不加密)
### 证书认证
- **单向认证**:客户端验证服务器证书
- 服务器提供数字证书
- 客户端验证证书有效性
- 防止连接到伪造的 Broker
- **双向认证**:客户端和服务器互相验证证书
- 提供更高的安全性
- 适用于高安全要求场景
- 需要为每个客户端颁发证书
## 2. 身份认证机制
### 用户名/密码认证
- **基本认证**:在 CONNECT 报文中携带用户名和密码
- **特点**:
- 实现简单
- 广泛支持
- 密码明文传输(需配合 TLS 使用)
- **配置示例**:
```
CONNECT
Client ID: client123
Username: user
Password: pass123
```
### Token 认证
- **JWT Token**:使用 JSON Web Token 进行认证
- **特点**:
- 无状态认证
- 支持过期时间
- 可携带自定义信息
- **适用场景**:分布式系统、微服务架构
### OAuth 2.0 认证
- **授权流程**:使用 OAuth 2.0 标准进行授权
- **特点**:
- 标准化的授权协议
- 支持多种授权模式
- 与现有身份系统集成方便
### 证书认证
- **客户端证书**:使用 X.509 证书进行身份验证
- **特点**:
- 安全性最高
- 无需传输密码
- 证书管理复杂
- **适用场景**:金融、医疗等高安全要求领域
## 3. 访问控制(ACL)
### ACL 规则
- **基于主题的权限**:控制客户端对特定主题的访问
- **权限类型**:
- 订阅(Subscribe):是否允许订阅主题
- 发布(Publish):是否允许发布到主题
- 读写(Read/Write):同时允许订阅和发布
### ACL 配置示例
```
# 用户 user1 可以发布到 home/#
user1 publish home/#
# 用户 user2 可以订阅 home/+/temperature
user2 subscribe home/+/temperature
# 管理员拥有所有权限
admin publish #
admin subscribe #
```
### ACL 实现方式
- **静态配置**:在配置文件中定义规则
- **数据库存储**:使用 MySQL、PostgreSQL 等数据库存储规则
- **动态 API**:通过 HTTP API 动态获取权限
- **集成外部系统**:与 LDAP、Active Directory 等集成
## 4. 会话安全
### Clean Session
- **Clean Session = true**:
- 断开连接后清除会话状态
- 不保存离线消息
- 适用于临时连接
- **Clean Session = false**:
- 保留会话状态
- 保存离线消息
- 适用于持久连接
### 会话超时
- **Keep Alive**:客户端定期发送心跳包
- **超时处理**:超过指定时间未收到心跳,断开连接
- **默认值**:通常为 60 秒
## 5. 消息安全
### 消息加密
- **端到端加密**:应用层对消息内容加密
- **加密算法**:AES、RSA 等
- **适用场景**:高敏感数据传输
### 消息签名
- **数字签名**:验证消息来源和完整性
- **防止篡改**:确保消息未被修改
- **适用场景**:关键指令、控制命令
## 6. 安全最佳实践
### 网络层
1. **使用 TLS**:始终使用 TLS 加密传输
2. **防火墙配置**:限制 MQTT 端口访问
3. **网络隔离**:将 MQTT Broker 放在内网
4. **VPN 访问**:远程访问使用 VPN
### 认证层
1. **强密码策略**:使用复杂密码,定期更换
2. **多因素认证**:对关键操作启用 MFA
3. **证书管理**:定期更新证书,及时撤销过期证书
4. **最小权限原则**:只授予必要的权限
### 应用层
1. **输入验证**:验证所有输入数据
2. **速率限制**:防止暴力破解和 DDoS 攻击
3. **日志审计**:记录所有操作日志
4. **安全监控**:实时监控异常行为
## 7. 常见安全威胁及防护
### 威胁类型
1. **中间人攻击**:使用 TLS 防护
2. **重放攻击**:使用时间戳和随机数
3. **暴力破解**:使用速率限制和账户锁定
4. **消息注入**:使用消息签名和验证
5. **拒绝服务**:使用连接数限制和资源配额
### 防护措施
- **定期安全审计**:检查配置和日志
- **漏洞扫描**:定期扫描系统漏洞
- **渗透测试**:模拟攻击测试安全性
- **安全更新**:及时更新 Broker 和依赖库
MQTT 的安全性需要从多个层面综合考虑,根据应用场景的安全要求选择合适的安全机制组合。
服务端 · 2月19日 19:18
MQTT 协议有哪些控制报文类型?各自的作用是什么?MQTT 协议定义了多种控制报文类型,每种报文都有特定的功能和格式。以下是 MQTT 协议的主要控制报文及其作用。
## MQTT 控制报文类型
### 1. CONNECT - 连接请求
- **方向**:客户端 → Broker
- **作用**:客户端向 Broker 请求建立连接
- **关键参数**:
- Client ID:客户端唯一标识符
- Clean Session:是否清除之前的会话状态
- Keep Alive:心跳间隔(秒)
- Username/Password:认证信息
- Will Message:遗嘱消息(客户端异常断开时发送)
- **响应**:CONNACK
### 2. CONNACK - 连接确认
- **方向**:Broker → 客户端
- **作用**:确认连接是否成功建立
- **关键参数**:
- Session Present:是否包含之前的会话状态
- Return Code:连接结果(0 表示成功)
- **返回码示例**:
- 0:连接成功
- 1:协议版本不支持
- 2:客户端 ID 不合法
- 3:服务器不可用
- 4:用户名或密码错误
- 5:未授权
### 3. PUBLISH - 发布消息
- **方向**:双向(客户端 ↔ Broker)
- **作用**:发布消息到指定主题
- **关键参数**:
- Topic Name:主题名称
- Packet Identifier:数据包标识符(QoS 1/2)
- QoS:服务质量级别(0/1/2)
- DUP:是否重复发送
- Retain:是否保留消息
- Payload:消息内容
- **响应**:
- QoS 0:无响应
- QoS 1:PUBACK
- QoS 2:PUBREC → PUBREL → PUBCOMP
### 4. PUBACK - 发布确认(QoS 1)
- **方向**:接收方 → 发布方
- **作用**:确认收到 QoS 1 消息
- **关键参数**:
- Packet Identifier:对应的消息 ID
### 5. PUBREC - 发布收到(QoS 2)
- **方向**:接收方 → 发布方
- **作用**:确认收到 QoS 2 消息的第一阶段
- **关键参数**:
- Packet Identifier:对应的消息 ID
- **响应**:PUBREL
### 6. PUBREL - 发布释放(QoS 2)
- **方向**:发布方 → 接收方
- **作用**:释放 QoS 2 消息的第二阶段
- **关键参数**:
- Packet Identifier:对应的消息 ID
- **响应**:PUBCOMP
### 7. PUBCOMP - 发布完成(QoS 2)
- **方向**:接收方 → 发布方
- **作用**:完成 QoS 2 消息的第三阶段
- **关键参数**:
- Packet Identifier:对应的消息 ID
### 8. SUBSCRIBE - 订阅主题
- **方向**:客户端 → Broker
- **作用**:订阅一个或多个主题
- **关键参数**:
- Packet Identifier:数据包标识符
- Topic Filter:主题过滤器(支持通配符)
- QoS:订阅的 QoS 级别
- **响应**:SUBACK
### 9. SUBACK - 订阅确认
- **方向**:Broker → 客户端
- **作用**:确认订阅结果
- **关键参数**:
- Packet Identifier:对应的 SUBSCRIBE 消息 ID
- Return Codes:每个主题的订阅结果
- **返回码示例**:
- 0-2:成功(QoS 级别)
- 128:订阅失败
### 10. UNSUBSCRIBE - 取消订阅
- **方向**:客户端 → Broker
- **作用**:取消订阅一个或多个主题
- **关键参数**:
- Packet Identifier:数据包标识符
- Topic Filter:要取消的主题过滤器
- **响应**:UNSUBACK
### 11. UNSUBACK - 取消订阅确认
- **方向**:Broker → 客户端
- **作用**:确认取消订阅
- **关键参数**:
- Packet Identifier:对应的 UNSUBSCRIBE 消息 ID
### 12. PINGREQ - 心跳请求
- **方向**:客户端 → Broker
- **作用**:检测连接是否活跃
- **触发条件**:Keep Alive 时间的一半
- **响应**:PINGRESP
### 13. PINGRESP - 心跳响应
- **方向**:Broker → 客户端
- **作用**:响应心跳请求,确认连接正常
- **响应时间**:通常在 1 秒内
### 14. DISCONNECT - 断开连接
- **方向**:客户端 → Broker
- **作用**:主动断开连接
- **特点**:
- 正常断开,不发送遗嘱消息
- Broker 清除客户端状态(Clean Session = true)
## 控制报文格式
### 固定头部(Fixed Header)
所有 MQTT 控制报文都包含固定头部:
```
+-----------------+------------------+
| Control Type | Flags |
| (4 bits) | (4 bits) |
+-----------------+------------------+
| Remaining Length (Variable) |
+-------------------------------------+
```
- **Control Type**:控制报文类型(1-14)
- **Flags**:标志位,根据报文类型有不同的含义
- **Remaining Length**:剩余长度(可变长度编码)
### 可变头部(Variable Header)
某些报文包含可变头部,包含报文特定的信息:
- Packet Identifier
- Topic Name
- Properties(MQTT 5.0)
### 有效载荷(Payload)
某些报文包含有效载荷:
- PUBLISH:消息内容
- CONNECT:客户端信息
- SUBSCRIBE:订阅列表
## QoS 级别与报文流程
### QoS 0 流程
```
Client ──PUBLISH──> Broker
```
### QoS 1 流程
```
Client ──PUBLISH──> Broker
Client <─PUBACK─── Broker
```
### QoS 2 流程
```
Client ──PUBLISH──> Broker
Client <─PUBREC─── Broker
Client ──PUBREL──> Broker
Client <─PUBCOMP── Broker
```
## 报文类型总结
| 报文类型 | 方向 | QoS | 说明 |
|---------|-----|-----|------|
| CONNECT | 客户端 → Broker | - | 建立连接 |
| CONNACK | Broker → 客户端 | - | 连接确认 |
| PUBLISH | 双向 | 0/1/2 | 发布消息 |
| PUBACK | 双向 | 1 | 发布确认 |
| PUBREC | 双向 | 2 | 发布收到 |
| PUBREL | 双向 | 2 | 发布释放 |
| PUBCOMP | 双向 | 2 | 发布完成 |
| SUBSCRIBE | 客户端 → Broker | - | 订阅主题 |
| SUBACK | Broker → 客户端 | - | 订阅确认 |
| UNSUBSCRIBE | 客户端 → Broker | - | 取消订阅 |
| UNSUBACK | Broker → 客户端 | - | 取消确认 |
| PINGREQ | 客户端 → Broker | - | 心跳请求 |
| PINGRESP | Broker → 客户端 | - | 心跳响应 |
| DISCONNECT | 客户端 → Broker | - | 断开连接 |
理解 MQTT 控制报文类型和流程对于实现 MQTT 客户端和服务器至关重要。
服务端 · 2月19日 19:17