结论先给出:👉 MQTT 是“支持超时重发机制的”,但这是
👉 由 QoS 等级 + 客户端/协议层实现的,并不是应用层显式写的那种“超时重发”API。
下面分层给你讲清楚。
一、MQTT 里“重发”是怎么来的?
MQTT 的可靠性,不是靠 TCP 超时重传那一套,而是靠 QoS(服务质量等级)+ 报文确认机制。
MQTT 的 3 个 QoS 等级
| QoS | 是否重发 | 可靠性 | 典型场景 |
|---|---|---|---|
| QoS 0 | ❌ 不重发 | 至多一次 | 传感器实时数据 |
| QoS 1 | ✅ 支持重发 | 至少一次 | 告警、状态上报 |
| QoS 2 | ✅ 支持重发 | 仅一次 | 金融、关键指令 |
二、QoS 1:最常用的“超时重发”
交互流程(QoS 1)
Client -> PUBLISH (QoS=1, PacketId=10)
Broker -> PUBACK (PacketId=10)
如果发生什么?
- 客户端 发送 PUBLISH
- 在一定时间内没收到 PUBACK
- 👉 客户端会重发 PUBLISH
- 重发时:
DUP = 1(重复标志)
也就是说:
QoS 1 天然支持“超时重发”
⚠️ 但注意:
- MQTT 协议 不规定具体超时时间
- 超时策略由 客户端库实现
三、QoS 2:更严格,但更复杂
QoS 2 是四步握手:
PUBLISH → PUBREC → PUBREL → PUBCOMP
任何一步:
- 超时
- 连接断开
👉 都会在重连后 按协议继续重发(靠 PacketId + DUP)
所以:
QoS 2 同样支持超时重发,而且是“状态机级别”的可靠传输
四、QoS 0:完全不重发
PUBLISH (QoS=0)
- 不等确认
- 不重发
- 可能丢
✔ 适合:
- 高频
- 不重要
- 可以容忍丢包
五、你关心的“超时”到底在哪?
MQTT 协议层:
- 有 重发机制
- ❌ 没有定义具体“多少毫秒算超时”
实际超时由谁决定?
👉 客户端 SDK / Broker 实现
比如:
| 客户端 | 超时/重发机制 |
|---|---|
| Eclipse Paho | 内部有 inflight 队列 + 定时器 |
| EMQX SDK | 可配置重发间隔 |
| mosquitto | 有 retry 机制 |
| 阿里云 / 华为云 SDK | 封装好的重试策略 |
六、Keep Alive ≠ 重发,但很重要
MQTT 还有一个容易混的点:
Keep Alive(心跳)
- PINGREQ / PINGRESP
- 用来:
- 检测连接是否断开
- ❌ 不是消息重发机制
但如果连接断了:
- QoS 1 / 2 的未确认消息
👉 在重连后会继续发送
七、一句话总结
✅ MQTT 支持超时重发机制
✔ 体现在 QoS 1 / QoS 2
❌ QoS 0 不支持
⏱ 超时时间由客户端库实现
🔁 重发靠 PacketId + DUP 标志
八、结合你常见的工程场景建议
如果你是在做 物联网 / 设备端 / 后台服务(你之前经常问这类):
- 状态、日志 → QoS 0
- 告警、控制指令 → QoS 1
- 必须只执行一次的命令 → QoS 2(慎用,性能开销大)