【嵌入式面试】MQTT 高频面试题
【嵌入式面试】MQTT 高频面试题
MQTT 是物联网设备接入的事实标准协议,嵌入式/物联网岗位面试几乎必考:从基础概念、报文流程到 QoS 机制、遗嘱与心跳,考点集中且细节多。本文整理了 MQTT 高频面试题 与精炼参考答案,覆盖协议原理、连接管理、QoS 与嵌入式落地场景。
基础概念
1. MQTT 是什么?为什么适合物联网?
MQTT(Message Queuing Telemetry Transport)是基于发布/订阅模式的轻量级消息协议,运行在 TCP/IP 之上,由 OASIS 标准化(3.1.1 / 5.0)。特点是协议头小(固定头仅 2 字节起)、带宽占用低、支持 QoS 分级与离线消息、心跳保活、遗嘱机制,非常适合低带宽、弱网、资源受限的嵌入式设备。典型应用包括传感器数据上报、设备远程控制、告警推送、OTA 升级等。
2. MQTT 的发布/订阅模型和传统的请求/响应模型有什么区别?
发布/订阅模型中,发送者(Publisher)和接收者(Subscriber)完全解耦,通过 Broker 中转、按主题匹配消息:发布者不知道谁在订阅,订阅者也不知道谁发布。请求/响应模型(如 HTTP)是客户端主动发起、服务端应答的一对一同步通信。解耦带来的好处:设备增减不影响其他节点、天然支持一对多广播、异步通信延迟低、扩展性好。
3. Broker 在 MQTT 中扮演什么角色?
Broker(代理/服务器)是消息中转中心:接收客户端 CONNECT,维护会话与订阅关系,把 PUBLISH 按主题匹配并转发给所有订阅者。它还负责 QoS 消息的确认与重发、心跳超时判定、遗嘱消息的代发、保留消息的存储与清除。常见实现有 EMQX、Mosquitto、HiveMQ 等,嵌入式轻量场景常用 Mosquitto。
连接与会话
4. MQTT 客户端连接和断开的过程是怎样的?
连接:客户端建立 TCP 连接后发送 CONNECT 报文(含 clientId、Clean Session、KeepAlive、用户名/密码、遗嘱等),Broker 回复 CONNACK(含返回码,0x00 表示成功)。正常断开:客户端发送 DISCONNECT 报文,Broker 清理连接且不发送遗嘱。异常断开:网络断开或心跳超时,Broker 判定连接异常,此时若设置了遗嘱则代发遗嘱消息。
5. CONNECT 报文里一般包含哪些关键字段?
clientId:客户端唯一标识,会话恢复依赖它;KeepAlive:心跳间隔;Clean Session:是否清理会话;遗嘱(Will Topic/Message/QoS/Retain):异常断开时代发;用户名密码(可选)。面试常问 clientId 重复会怎样——Broker 会踢掉旧连接,同一 clientId 只能存在一个活动连接。
6. 什么是 KeepAlive 心跳?有什么用?
KeepAlive 是 CONNECT 中约定的时间间隔(秒),客户端在间隔内至少发送一次报文,空闲时发 PINGREQ,Broker 回 PINGRESP。作用是检测半开连接(网络异常但 TCP 未断开):Broker 在 1.5 倍 KeepAlive 时间内没收到任何报文,就判定客户端离线,清理连接并触发遗嘱。嵌入式弱网环境下,KeepAlive 用于快速感知设备掉线并及时告警。
7. Clean Session(会话清理)是什么?与会话持久化有什么关系?
Clean Session=1:连接断开后 Broker 不保存任何会话,订阅关系与未确认消息全部丢弃,重连需重新订阅(无状态)。Clean Session=0:断开后 Broker 持久化会话(订阅关系、QoS1/2 未确认消息),设备用相同 clientId 重连后自动恢复订阅,离线期间的消息在 QoS 允许下补发。弱网设备建议 Clean Session=0 保证不掉订阅;注意 MQTT 5.0 已改为 Clean Start + 会话过期时间的机制。
QoS 机制
8. MQTT 的 QoS 0 是什么?适用什么场景?
QoS 0(At most once,至多一次):发送方尽力发送,不等待任何确认,可能丢失,但开销最小、速度最快。适用可容忍丢包的周期性数据(如温湿度上报、位置信息),或本地已有可靠链路的场景。面试点:QoS 0 下 Broker 不做重发,也不为离线客户端保存消息。
9. QoS 1 的流程是怎样的?为什么可能重复?
流程:发送方发 PUBLISH(QoS1) → Broker 收到后回复 PUBACK → 发送方收到即完成。若超时未收到 PUBACK,发送方会重发,重发报文 DUP 标志位置 1(PacketId 相同),因此消息是至少一次(At least once),可能重复到达。接收方需要按 PacketId 去重(记录已处理的 PacketId),适用于不能丢但可以容忍重复的数据。
10. QoS 2 的四次握手流程是什么?
发送方发 PUBLISH(QoS2) → Broker 回 PUBREC → 发送方回 PUBREL → Broker 回 PUBCOMP,完成恰好一次(Exactly once)投递。关键点:收到 PUBREC 前可重发 PUBLISH;收到 PUBREC 后只能重发 PUBREL,不能再发 PUBLISH;Broker 通过状态机保证消息不重不漏。代价是报文交互最多、延迟最大,只用于关键控制类消息(如远程开关、固件升级指令)。
11. 三种 QoS 如何选择?
核心是可靠性与开销的权衡:可容忍丢失用 QoS0(最省流量);要求不丢、容忍重复用 QoS1(最常用);要求严格不重不漏用 QoS2(如支付、关键控制)。注意发布方与订阅方可以分别指定 QoS,Broker 按两者中较低的那一个 QoS 投递。
主题与消息特性
12. MQTT 主题的层级和通配符(+ 和 #)怎么用?
主题是 UTF-8 字符串,层级用 / 分隔,如 device/1/temp。+ 匹配单层(device/+/temp 匹配任意设备),# 匹配多层且只能出现在末尾(device/# 匹配 device 下所有层级)。订阅时可以使用通配符,发布时不能使用通配符。特殊规则:以 $ 开头的主题(如 $SYS)不能被通配符匹配,Broker 用它发布自身运行信息。
13. 保留消息(Retain)是什么?有什么用?
发布时 Retain=1,Broker 会保存该主题的最后一条消息;新订阅者订阅该主题时立即收到这条保留消息,无需等下一次发布。典型应用:设备状态(在线/离线、当前配置)——新设备/新订阅者上线即可拿到最新状态。清除方式:向该主题发布空 payload 且 Retain=1 的消息。
14. 遗嘱消息(LWT, Last Will and Testament)是什么?
客户端在 CONNECT 中声明遗嘱主题/消息/QoS/Retain;当客户端异常断开(网络断开、心跳超时、协议错误)时,Broker 代替客户端发布遗嘱消息。正常 DISCONNECT 退出不触发遗嘱。作用:让其他订阅者感知设备"异常掉线",如把设备状态置为离线并告警。面试常追问:遗嘱和保留消息常配合使用——掉线时发遗嘱覆盖"在线"状态。
与 HTTP 对比及嵌入式应用
15. 与 HTTP 轮询相比,MQTT 有哪些优势?
连接方式:HTTP 是短连接、请求/响应、单向;MQTT 是长连接、双向推送,服务端可主动下发指令,实时性好。开销:MQTT 固定头仅 2 字节起,HTTP 头部开销大;MQTT 用心跳维持长连接,避免频繁建连。可靠性:MQTT 提供 QoS 分级、离线消息、遗嘱检测;HTTP 轮询延迟取决于轮询间隔,且存在空轮询的带宽浪费。大量设备接入时,MQTT 的 Broker 转发模型扩展性远好于 HTTP 轮询。
16. MQTT 报文的基本结构是怎样的?
每个报文由固定报头开始:4 位报文类型 + 4 位标志位 + 剩余长度字段(1~4 字节的可变字节整数编码,每字节 7 位有效位、最高位指示续段)。部分报文还有可变报头和载荷。常考细节:QoS、DUP、Retain 都位于 PUBLISH 报文固定报头的标志位中。
17. 为什么 MQTT 适合弱网/低带宽的嵌入式环境?
报文开销极小、可用 QoS0 换取低延迟、KeepAlive 维持长连接避免频繁握手、断线可自动重连并恢复会话(Clean Session=0),Broker 还能缓存离线消息等设备上线补发。配合遗嘱可快速感知掉线。嵌入式常用实现:paho-mqtt(C/Python)、esp-mqtt(ESP-IDF)、基于 lwIP 的 MQTT 客户端等。
18. 嵌入式设备上 MQTT 的典型应用有哪些?
数据上报:传感器采集温湿度、电量等周期发布到云端(QoS0/1)。远程控制:云端下发指令控制设备(QoS1/2,如开关、参数配置)。状态同步:用保留消息 + 遗嘱维护设备在线状态。OTA 升级:云端发布升级指令与固件分段消息。告警:设备异常时主动发布告警主题。低功耗场景可配置长 KeepAlive,或休眠唤醒后批量上报。
19. MQTT 客户端断线重连时要注意什么?
使用固定 clientId 并设 Clean Session=0 以恢复订阅与离线消息;若会话被清理需重新订阅通配符主题。注意 QoS1/2 重发消息的 PacketId 去重,避免重复处理业务。重连失败要按指数退避策略重试,避免断线风暴。配合遗嘱:重连成功后主动发布状态消息并更新遗嘱内容。
20. QoS1 的 DUP 标志和去重是怎么工作的?
发送方重发 QoS1/2 的 PUBLISH 时,将 DUP 标志置 1,表示该报文是重复发送(PacketId 与上次相同)。接收方(Broker 或订阅客户端)收到 DUP=1 的消息后,根据 PacketId 判断是否已处理过,已处理则不再重复处理,保证业务层幂等。面试点:DUP 只是"发送方认为可能重复"的提示,不保证接收方一定收到过原消息,去重要靠接收方自己维护状态。

