MQTT面试题
MQTT面试题
本章汇总 MQTT 相关的高频面试题,涵盖基础概念、协议原理、实践应用等方面。
基础概念
1. 什么是 MQTT?它有什么特点?
答案:
MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模式的轻量级消息传输协议。
主要特点:
- 轻量级:协议头最小只有 2 字节,适合带宽受限的网络
- 发布/订阅模式:解耦消息发送者和接收者
- QoS 机制:提供三种服务质量等级,保证消息可靠性
- 遗嘱消息:客户端异常断开时自动发布预设消息
- 保留消息:新订阅者可以立即收到主题的最后一条消息
- 低功耗:适合物联网设备和移动应用
2. MQTT 和 HTTP 有什么区别?
答案:
| 特性 | MQTT | HTTP |
|---|---|---|
| 通信模式 | 发布/订阅 | 请求/响应 |
| 连接方式 | 长连接 | 短连接(HTTP/1.1 可复用) |
| 头部开销 | 2 字节起 | 数百字节 |
| 双向通信 | 原生支持 | 需要轮询或 WebSocket |
| QoS | 支持 | 不支持 |
| 适用场景 | 物联网、实时通信 | Web 应用、API |
为什么物联网更适合 MQTT:
- 设备资源有限,需要轻量级协议
- 网络不稳定,需要 QoS 保证
- 需要服务器主动推送消息
- 需要低功耗,长连接比频繁建连更省电
3. MQTT 的三种 QoS 等级有什么区别?
答案:
| QoS | 名称 | 特点 | 适用场景 |
|---|---|---|---|
| 0 | At most once | 最多一次,可能丢失 | 传感器周期上报 |
| 1 | At least once | 至少一次,可能重复 | 设备状态、控制指令 |
| 2 | Exactly once | 恰好一次,不丢不重 | 金融交易、计费 |
QoS 1 流程:
Publisher --> PUBLISH --> Broker
Publisher <-- PUBACK <-- BrokerQoS 2 流程(四次握手):
Publisher --> PUBLISH --> Broker
Publisher <-- PUBREC <-- Broker
Publisher --> PUBREL --> Broker
Publisher <-- PUBCOMP <-- BrokerQoS 降级:最终 QoS = min(发布 QoS, 订阅 QoS)
4. Clean Session 的作用是什么?
答案:
Clean Session 控制会话的持久性:
Clean Session = true:
- 连接时清除之前的会话状态
- 断开时不保存会话状态
- 不会收到离线期间的消息
- 适用于临时客户端
Clean Session = false:
- 连接时恢复之前的会话状态
- 断开时保存会话状态(订阅、未确认消息)
- 重连后可以收到离线期间的 QoS 1/2 消息
- 适用于需要离线消息的客户端
5. 遗嘱消息(Last Will)是什么?什么时候触发?
答案:
遗嘱消息是客户端在连接时预设的消息,当客户端异常断开时,Broker 自动发布该消息。
触发条件:
- 网络故障导致连接断开
- 客户端在 Keep Alive 时间内无响应
- 客户端未发送 DISCONNECT 直接关闭连接
- Broker 因协议错误关闭连接
不触发的情况:
- 客户端正常发送 DISCONNECT 断开
应用场景:设备在线状态监控
client.will_set("device/status", "offline", qos=1, retain=True)协议原理
6. MQTT 报文的基本结构是什么?
答案:
MQTT 报文由三部分组成:
+------------------+------------------+------------------+
| Fixed Header | Variable Header | Payload |
| (必须) | (部分报文) | (部分报文) |
+------------------+------------------+------------------+固定头(2+ 字节):
- 第 1 字节:报文类型(4 bits)+ 标志位(4 bits)
- 第 2+ 字节:剩余长度(变长编码,1-4 字节)
剩余长度编码:每字节低 7 位表示数值,最高位表示是否有后续字节,最大可表示约 256MB。
7. MQTT 主题通配符 + 和 # 有什么区别?
答案:
| 通配符 | 匹配范围 | 位置限制 | 示例 |
|---|---|---|---|
+ | 单层 | 任意位置 | sensor/+/temp |
# | 多层 | 必须在最后 | sensor/# |
示例:
订阅: home/+/temperature
匹配: home/room1/temperature ✓
home/room2/temperature ✓
home/floor1/room1/temperature ✗
订阅: home/#
匹配: home ✓
home/room1 ✓
home/room1/temperature ✓注意:通配符只能用于订阅,不能用于发布。
8. MQTT 的心跳机制是如何工作的?
答案:
MQTT 使用 Keep Alive 机制检测连接是否存活:
- 客户端在 CONNECT 报文中指定 Keep Alive 时间(秒)
- 客户端必须在 Keep Alive 时间内发送至少一个报文
- 如果没有数据要发送,客户端发送 PINGREQ
- Broker 收到 PINGREQ 后回复 PINGRESP
- 如果 1.5 × Keep Alive 时间内没有收到任何报文,认为连接断开
Client Broker
| |
|------ PINGREQ -------->|
|<----- PINGRESP --------|
| |9. 保留消息(Retained Message)有什么作用?
答案:
保留消息是 Broker 为每个主题保存的最后一条消息,新订阅者会立即收到该消息。
特点:
- 每个主题只保留一条消息
- 新订阅者立即收到保留消息
- 发送空消息可以清除保留消息
应用场景:
- 设备配置下发
- 设备状态同步
- 系统公告
# 发布保留消息
client.publish("device/config", '{"interval": 60}', retain=True)
# 清除保留消息
client.publish("device/config", "", retain=True)MQTT 5.0
10. MQTT 5.0 相比 3.1.1 有哪些主要改进?
答案:
| 特性 | 说明 |
|---|---|
| 原因码 | 所有响应报文都有详细的原因码 |
| 属性 | 可以在报文中携带额外信息 |
| 共享订阅 | 多个客户端组成消费组,负载均衡 |
| 消息过期 | 消息可以设置过期时间 |
| 主题别名 | 用整数代替主题字符串,减少带宽 |
| 用户属性 | 自定义键值对 |
| 请求/响应 | 原生支持请求/响应模式 |
| 会话过期 | 精确控制会话过期时间 |
| 流控 | 控制未确认消息数量 |
11. MQTT 5.0 的共享订阅是什么?
答案:
共享订阅允许多个客户端组成消费组,实现消息的负载均衡分发。
格式:$share/{group}/{topic}
+-- Consumer 1 (收到消息1, 4, 7...)
|
Broker --消息--> $share/group/topic --+-- Consumer 2 (收到消息2, 5, 8...)
|
+-- Consumer 3 (收到消息3, 6, 9...)应用场景:
- 高吞吐量消息处理
- 消费者水平扩展
- 避免消息重复处理
实践应用
12. 如何设计物联网平台的 MQTT 主题结构?
答案:
推荐结构:
{组织}/{产品}/{设备ID}/{数据类型}
示例:
iot/sensor/device001/telemetry # 遥测数据
iot/sensor/device001/event # 事件上报
iot/sensor/device001/command # 下行指令
iot/sensor/device001/response # 指令响应
iot/sensor/device001/status # 设备状态设计原则:
- 层级清晰,3-5 层为宜
- 使用小写字母和连字符
- 避免以
/开头 - 预留通配符订阅的可能性
13. 如何保证 MQTT 消息不丢失?
答案:
使用 QoS 1 或 QoS 2
client.publish("topic", "message", qos=1)使用持久会话
client = mqtt.Client(clean_session=False)配置消息持久化
# Broker 配置 persistence = true监控消息队列
- 避免队列溢出
- 及时消费消息
实现应用层确认
- 业务层消息确认
- 失败重试机制
14. 如何处理 MQTT 消息重复?
答案:
QoS 1 可能产生重复消息,需要在应用层处理:
方案1:消息ID去重
class MessageDeduplicator:
def __init__(self):
self.seen = set()
def is_duplicate(self, msg_id):
if msg_id in self.seen:
return True
self.seen.add(msg_id)
return False方案2:幂等设计
def process_order(order_id, data):
if order_exists(order_id):
return # 幂等,直接返回
create_order(order_id, data)方案3:使用 QoS 2(性能开销大)
15. MQTT 集群是如何实现消息路由的?
答案:
MQTT 集群通过路由表实现跨节点消息路由:
- 订阅同步:客户端订阅时,订阅信息同步到所有节点
- 路由表:每个节点维护全局路由表
- 消息转发:消息发布时,根据路由表转发到订阅者所在节点
Client A (订阅 topic/a) Client B (发布到 topic/a)
| |
v v
+-------+ +-------+
| Node1 |<---- 集群通信 ---->| Node2 |
+-------+ +-------+
|
v
消息投递给 Client A16. 如何优化 MQTT 的性能?
答案:
Broker 层面:
- 调整系统内核参数(文件描述符、TCP 参数)
- 配置合适的连接数和队列大小
- 使用集群分散负载
客户端层面:
- 选择合适的 QoS(非必要不用 QoS 2)
- 使用连接池复用连接
- 批量发布消息
消息层面:
- 压缩消息内容
- 使用高效的序列化格式(Protobuf、MessagePack)
- 使用主题别名(MQTT 5.0)
主题设计:
- 避免过深的层级
- 减少通配符订阅
- 合理规划主题结构
安全相关
17. MQTT 有哪些安全机制?
答案:
传输层安全(TLS/SSL)
- 加密通信,防止窃听
- 证书验证,防止中间人攻击
认证机制
- 用户名密码认证
- 客户端证书认证(mTLS)
- Token 认证(JWT)
访问控制(ACL)
- 控制客户端对主题的访问权限
- 支持发布/订阅权限分离
其他
- 连接速率限制
- 消息大小限制
- 客户端 ID 白名单
18. 如何防止 MQTT 客户端访问未授权的主题?
答案:
通过 ACL(访问控制列表)配置:
# 允许设备只能访问自己的主题
pattern readwrite device/%c/#
# 允许管理员访问所有主题
user admin
topic readwrite #
# 禁止访问系统主题
topic deny $SYS/#最佳实践:
- 实施最小权限原则
- 使用主题模式匹配(%c 代表 Client ID)
- 定期审计权限配置
小结
MQTT 面试题主要考察:
- 基础概念:协议特点、QoS、会话管理
- 协议原理:报文结构、主题匹配、心跳机制
- MQTT 5.0:新特性、共享订阅
- 实践应用:主题设计、可靠性保证、性能优化
- 安全机制:TLS、认证、ACL
掌握这些知识点,能够应对大多数 MQTT 相关的面试问题。
