乐闻世界logo
搜索文章和话题

MQTT

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