Broker 与客户端角色
Broker 与客户端角色
Section titled “Broker 与客户端角色”本节详细介绍 MQTT 中 Broker 和客户端的角色、功能和工作方式。学习完成后,您将能够:
- 理解 MQTT Broker 的核心功能和职责
- 区分不同客户端类型及其作用
- 掌握 Broker 的连接管理和会话维护机制
- 评估不同场景下的 Broker 选型
在开始本节之前,请确保:
- 理解发布-订阅架构
- Mosquitto Broker 已安装运行
- 已安装 MQTT 命令行工具或 MQTT Explorer
Broker Deep Dive
Section titled “Broker Deep Dive”Broker Core Responsibilities
Section titled “Broker Core Responsibilities”MQTT Broker 是消息系统的核心枢纽,负责以下关键功能:
┌───────────────────────────────────────────────────────┐│ MQTT Broker │├───────────────────────────────────────────────────────┤│ ││ 1. 消息接收与路由 ││ ┌────────┐ ┌──────────┐ ┌────────┐ ││ │ Publisher│───→│ Topic 路由 │───→│Subscriber│ ││ └────────┘ └──────────┘ └────────┘ ││ ││ 2. 连接管理 ││ ┌──────────────────────────────────────────────┐ ││ │ 客户端认证 → 会话创建 → 连接保持 → 断线检测 │ ││ └──────────────────────────────────────────────┘ ││ ││ 3. 消息质量管理 ││ QoS 0: 直接转发 ││ QoS 1: 等待 PUBACK ││ QoS 2: 双段握手 (PUBREC → PUBREL → PUBCOMP) ││ ││ 4. 状态管理 ││ - 保留消息 (Retained Messages) ││ - 遗嘱消息 (Last Will) ││ - 离线消息缓存 (Pending Messages) ││ │└───────────────────────────────────────────────────────┘Topic-Based Message Routing
Section titled “Topic-Based Message Routing”Broker 根据 Topic 进行消息路由的核心机制:
发布消息: factory/zone1/temperature │ ↓ ┌─────────────────┐ │ Topic 匹配引擎 │ └─────────────────┘ │ ┌──────────┼──────────┐ ↓ ↓ ↓ [Subscribers] [Subscribers] [Subscribers] factory/# factory/+/temperature factory/zone1/temperature匹配规则:
- 完全匹配:Topic 完全相同时直接转发
- 通配符订阅:
+匹配单级,#匹配多级 - 系统 Topic:以
$SYS/开头的内部管理 Topic
Client Types
Section titled “Client Types”MQTT Client Categories
Section titled “MQTT Client Categories”1. Publisher(发布者)
- 功能:向特定 Topic 发送消息
- 特点:不需要订阅任何 Topic
- 典型设备:传感器节点、数据采集器
2. Subscriber(订阅者)
- 功能:接收订阅 Topic 的消息
- 特点:不需要发布任何消息
- 典型设备:仪表板、数据存储、手机 App
3. Publisher + Subscriber
- 功能:同时发布和订阅
- 特点:双向通信能力
- 典型设备:智能插座(上报状态 + 接收控制命令)
Client Connection States
Section titled “Client Connection States”MQTT 客户端连接状态管理:
状态转换图:
DISCONNECTED │ │ CONNECT (发送 CONNECT 报文) ↓CONNECTING │ │ CONNACK (接收连接确认) ↓CONNECTED ←──────────────────┐ │ │ │ Publish/Subscribe │ PING (心跳保活) ↓ │ACTIVE ──────────────────────┘ │ │ DISCONNECT / 连接中断 ↓DISCONNECTED → 触发 Last Will (遗嘱消息)Client Identifier (Client ID)
Section titled “Client Identifier (Client ID)”每个 MQTT 客户端连接时必须使用唯一的 Client ID:
Client ID 命名规范:
✅ 推荐格式: esp32_factory_001 # 设备类型_位置_编号 sensor_temp_zone1 # 传感器类型_区域 dashboard_main # 应用类型_名称
❌ 避免格式: esp32 # 太通用,容易冲突 client_1 # 毫无信息量 test # 仅用于测试Client ID 管理:
// ESP32 中自动生成唯一 Client ID#include <WiFi.h>
String generateClientID() { // 使用 MAC 地址生成唯一 ID uint64_t chipid = ESP.getEfuseMac(); String clientID = "esp32_" + String((uint16_t)(chipid >> 32), HEX) + String((uint32_t)chipid, HEX); return clientID;}Connection Management
Section titled “Connection Management”CONNECT/CONNACK Handshake
Section titled “CONNECT/CONNACK Handshake”MQTT 连接建立过程:
Client Broker │ │ │─── CONNECT ──────────────────────→│ │ Protocol Level: 4 (v3.1.1) │ │ Client ID: esp32_001 │ │ Clean Session: true │ │ Keep Alive: 60 seconds │ │ Username: (optional) │ │ Password: (optional) │ │ Last Will Topic: (optional) │ │ Last Will Message: (optional) │ │ │ │←── CONNACK ───────────────────────│ │ Session Present: false │ │ Return Code: 0 (Accepted) │ │ │ │======== Connection Established ====│CONNACK 返回码说明:
| 返回码 | 含义 | 处理方式 |
|---|---|---|
| 0 | 连接接受 | 正常通信 |
| 1 | 不接受的协议版本 | 检查 MQTT 版本 |
| 2 | 标识符被拒 | 更换 Client ID |
| 3 | 服务器不可用 | 稍后重试 |
| 4 | 用户名或密码错误 | 检查认证信息 |
| 5 | 未授权 | 检查权限配置 |
Keep Alive Mechanism
Section titled “Keep Alive Mechanism”心跳机制维护客户端连接状态:
keepAlive 间隔 (客户端声明,如 60 秒) │ ├── 客户端应当在 1.5×keepAlive 内发送 PINGREQ │ ├── Broker 如果超过 1.5×keepAlive 未收到消息 │ 或 PINGREQ,则判定客户端离线 │ └── 离线后 Broker 发送 Last Will 消息Broker Configuration
Section titled “Broker Configuration”Mosquitto Basic Configuration
Section titled “Mosquitto Basic Configuration”# mosquitto.conf 核心配置
# 监听端口listener 1883 # 非加密 MQTTlistener 9001 # WebSocket(浏览器用)
# 认证配置allow_anonymous false # 禁止匿名连接password_file /mosquitto/config/passwd # 密码文件
# 持久化配置persistence truepersistence_location /mosquitto/data/
# 日志配置log_dest file /mosquitto/log/mosquitto.loglog_type allconnection_messages true
# 客户端限制max_connections -1 # 无限制max_inflight_messages 20 # 最大并发消息数max_queued_messages 100 # 最大队列消息数
# 大小限制message_size_limit 0 # 无限制Client Authentication
Section titled “Client Authentication”# 创建用户密码docker exec -it mosquitto mosquitto_passwd -c /mosquitto/config/passwd esp32_user# 输入密码并确认
# 查看已创建的用户cat mosquitto/config/passwdBroker Selection Guide
Section titled “Broker Selection Guide”Mosquitto vs EMQX
Section titled “Mosquitto vs EMQX”| 特性 | Mosquitto | EMQX |
|---|---|---|
| 开发语言 | C | Erlang |
| 许可证 | Eclipse Public License | Apache 2.0 (开源版) |
| 单节点连接数 | ~10,000 | ~1,000,000 |
| 集群支持 | 有限(桥接) | 原生支持 |
| 消息路由 | 单线程 | 多线程高并发 |
| Web Dashboard | 无(需第三方) | 内置 |
| 规则引擎 | 无 | 内置 |
| 适合场景 | 中小型部署 | 大规模/高可用部署 |
| 部署复杂度 | 低(单一二进制) | 中(依赖 Erlang) |
| 资源占用 | 低(~10MB 内存) | 中(~100MB+ 内存) |
Recommendation Matrix
Section titled “Recommendation Matrix”| 场景 | 推荐 Broker | 理由 |
|---|---|---|
| 个人项目/学习 | Mosquitto | 简单、轻量 |
| 小型企业 (< 100 设备) | Mosquitto | 够用、配置简单 |
| 中型部署 (100-1000 设备) | Mosquitto 或 EMQX | 视复杂度决定 |
| 大规模部署 (1000+) | EMQX | 集群能力 |
| 需要高可用 | EMQX 集群 | 原生支持 |
| IoT 云平台 | EMQX 企业版 | 规则引擎+数据桥接 |
验证 Broker 运行
Section titled “验证 Broker 运行”# 检查 Broker 状态docker ps | grep mosquitto
# 查看日志docker logs mosquitto --tail 20
# 测试连接mosquitto_sub -h localhost -t "test" -v &mosquitto_pub -h localhost -t "test" -m "hello"
# 预期:订阅端收到 "hello"Issue 1: 连接被拒绝
Section titled “Issue 1: 连接被拒绝”症状:客户端无法连接 Broker
可能原因:
- Broker 未运行
- 端口被防火墙阻止
- 认证失败
解决方案:
# 检查 Broker 是否运行docker ps | grep mosquitto
# 检查端口netstat -an | grep 1883
# 临时允许匿名连接测试# 修改 mosquitto.conf:# allow_anonymous trueIssue 2: 客户端 ID 冲突
Section titled “Issue 2: 客户端 ID 冲突”症状:一个客户端频繁掉线重连
可能原因:多个客户端使用相同的 Client ID
解决方案:
- 确保每个设备使用唯一的 Client ID
- ESP32 使用 MAC 地址生成 Client ID
- 使用 UUID 作为 Client ID
Summary
Section titled “Summary”本节要点总结:
- Broker 核心功能:消息路由、连接管理、QoS 支持、状态管理
- 客户端类型:Publisher、Subscriber 或两者兼具
- 连接管理:CONNECT/CONNACK 握手机制,Keep Alive 心跳保活
- 身份标识:Client ID 必须唯一,建议使用设备特征生成
- Broker 选型:Mosquitto 适合中小规模,EMQX 适合大规模高可用