当前位置: 首页 > news >正文

MQTT协议之QoS0(<=1)、QoS1(>=1)、QoS2(=1)详解

目录

✅ QoS 0

1. “QoS 0:最多一次(At most once)”

2. “消息发布依赖于底层 TCP/IP 网络”

3. “即:<=1” 是什么意思?

底层实现细节(QoS 0)

总结

✅ QoS 1

底层实现机制(关键点)

1. 使用 Packet Identifier(包标识符)

2. 需要确认机制(PUBACK)

3. 基于 TCP,但增加应用层可靠性

QoS 1 消息传递流程(以发布者 → Broker 为例)

1、如果 PUBACK 丢失(或网络延迟):

端到端 QoS:发布者 ↔ Broker ↔ 订阅者

注意事项与最佳实践

总结

✅QoS 2 

底层实现机制:四步握手(Four-Step Handshake)

1、详细交互流程(以 Client → Broker 为例)

2、关键状态管理:

3、如何防止重复?

端到端 QoS 与逐跳特性

注意事项与局限性

总结

📊 三种 QoS 对比总结


MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,广泛用于物联网(IoT)场景。在 MQTT 中,QoS(Quality of Service,服务质量等级)定义了消息传递的可靠性级别。其中:

  • QoS 0:最多一次(At most once)
  • QoS 1:至少一次(At least once)
  • QoS 2:恰好一次(Exactly once)

✅ QoS 0

1. “QoS 0:最多一次(At most once)”

  • 这意味着消息可能送达一次,也可能完全不送达
  • 不会重复(因为没有重传机制),但可能丢失
  • 所以严格来说:“会发生消息丢失”,但不会发生重复

❗注意:你原文说“会发生消息丢失或重复”——这是对 QoS 0 的常见误解。QoS 0 不会重复,只有 QoS 1 可能重复(因重传但未确认)。

2. “消息发布依赖于底层 TCP/IP 网络”

  • MQTT 基于 TCP(可靠连接),但 QoS 0 不添加任何应用层确认或重传机制
  • 它只是把消息通过 TCP socket 发出去,就认为完成了。
  • 如果 TCP 层成功传输,消息就送达;如果网络闪断、客户端崩溃、中间代理丢包等,应用层不会知道,也不会重发
  • 因此,其可靠性完全取决于 TCP 的当前状态。虽然 TCP 本身是可靠的(有重传、校验、顺序保证),但如果连接在发送前或发送中中断,QoS 0 消息就会丢失。

💡 补充:TCP 保证的是“已发送的数据可靠传输”,但 QoS 0 在调用 send() 后就不管了。如果 send() 成功写入内核缓冲区,但随后连接断开,数据可能根本没到对方——而发布者不知道。

3. “即:<=1” 是什么意思?

  • 这里的 “<=1” 是一种非正式表达,意思是:
    • 消息被接收的次数 小于或等于 1 次
    • 即:0 次(丢失) 或 1 次(成功)绝不会 >1 次(不重复)
  • 所以更准确的说法是:“最多一次交付”

底层实现细节(QoS 0)

当客户端使用 QoS 0 发布消息时,具体流程如下:

  1. 构造 PUBLISH 报文

    • 固定报头(Fixed Header)中 QoS 字段设为 00(二进制)。
    • 不包含 Packet Identifier(包标识符)(因为不需要确认)。
  2. 通过 TCP socket 直接发送

    [PUBLISH] Topic: "sensor/temp"Payload: "25.3"QoS: 0
    

    → 直接 write() 到 TCP socket。

  3. 无等待、无确认

    • 发布者发送后立即认为完成,继续执行后续代码。
    • 不等待 PUBACK(因为 QoS 0 没有 PUBACK)。
    • 代理(Broker)收到后直接转发给订阅者(同样用 QoS 0,除非订阅时指定了更高 QoS)。
  4. 失败情况

    • 若 TCP 连接在 send() 前已断开 → 消息根本发不出去。
    • 若 send() 成功但网络随后中断 → 消息可能卡在网络中丢失。
    • 无论哪种情况,发布者不会感知,也不会重试

总结

特性QoS 0
交付保证最多一次(At most once)
是否可能丢失✅ 是
是否可能重复❌ 否
是否使用 Packet ID❌ 否
是否需要 ACK❌ 否
依赖底层完全依赖 TCP 的瞬时可用性
适用场景对可靠性要求不高、高频数据(如传感器读数)、节省带宽

MQTT 的 QoS 1(Quality of Service Level 1) 表示 “至少一次”(At least once) 的消息传递语义。

这意味着:

消息一定会被接收方收到,但可能会收到多次(即可能重复)。

下面我们从语义、底层实现机制、流程细节和注意事项几个方面详细解释 QoS 1。


✅ QoS 1

  • 保证送达:发布者会确保消息最终被 Broker(或订阅者)收到。
  • 允许重复:由于采用“发了就重试直到确认”的机制,如果确认(ACK)丢失,发布者会重发,导致接收方可能收到多份相同消息。
  • 交付次数 ≥ 1:所以常写作 “≥1”。

📌 注意:QoS 1 不保证“恰好一次”,这是 QoS 2 的目标。


底层实现机制(关键点)

1. 使用 Packet Identifier(包标识符)
  • 每个 QoS 1(或 QoS 2)的 PUBLISH 报文都包含一个 16 位的非零 Packet ID
  • 这个 ID 在同一连接内对发送方是唯一的(直到收到对应 ACK 后可复用)。
  • 用于匹配请求与确认。
2. 需要确认机制(PUBACK)
  • 发布者发送 PUBLISH(QoS=1)后,必须等待接收方返回 PUBACK
  • 只有收到 PUBACK,发布者才认为该消息成功投递,可以释放该 Packet ID。
  • 如果没收到 PUBACK(比如超时),发布者会重发相同的 PUBLISH 报文(含相同 Packet ID)
3. 基于 TCP,但增加应用层可靠性
  • 虽然底层是可靠的 TCP,但 TCP 无法解决“应用层是否处理了消息”的问题。
  • QoS 1 在 MQTT 协议层面增加了“应用级 ACK”,确保逻辑上的送达。

QoS 1 消息传递流程(以发布者 → Broker 为例)

假设客户端 A 向 Broker 发布一条 QoS 1 消息:

[Client A]                     [Broker]|                              ||--- PUBLISH (QoS=1, PID=10) ->||                              ||<-- PUBACK (PID=10) ----------||                              |✅ 消息确认完成
1、如果 PUBACK 丢失(或网络延迟):
[Client A]                     [Broker]|                              ||--- PUBLISH (QoS=1, PID=10) ->|  // 第一次发送|                              |  // Broker 收到,处理,并发 PUBACK|           X<-- PUBACK -------|  // 但 ACK 丢了!|                              ||--- PUBLISH (QoS=1, PID=10) ->|  // 超时后重发(相同 PID)|                              |  // Broker 再次收到(重复)|<-- PUBACK (PID=10) ----------|  // 再次回复 PUBACK|                              |✅ 最终确认,但 Broker 处理了两次!

💡 因此:接收方必须具备“去重”能力(如通过 Packet ID 或业务唯一 ID),否则会出现重复处理。


端到端 QoS:发布者 ↔ Broker ↔ 订阅者

MQTT 的 QoS 是**逐跳(hop-by-hop)**的,不是端到端的。

  • 发布者到 Broker 的 QoS 由发布时指定
  • Broker 到订阅者的 QoS 取决于订阅时请求的 QoS 和发布 QoS 的较小值

例如:

  • 客户端发布 QoS 1 到主题 sensor/data
  • 订阅者订阅该主题时请求 QoS 2
  • 实际投递给订阅者的 QoS = min(1, 2) = QoS 1

所以,即使订阅者想要更高可靠性,也不能超过发布者提供的 QoS。


注意事项与最佳实践

项目说明
重复处理应用层必须幂等(idempotent),能安全处理重复消息
资源开销比 QoS 0 多一次往返(RTT),带宽略高(含 Packet ID 和 PUBACK)
适用场景需要可靠送达但可容忍重复的场景,如控制指令、告警通知
不要滥用对高频传感器数据用 QoS 1 会显著增加网络和 Broker 负担

总结

QoS 1 通过“发送 + 等待 PUBACK + 超时重传”机制,确保消息至少被接收一次。但由于重传可能导致重复,接收方必须实现幂等处理。它在可靠性和效率之间取得了良好平衡,是实际应用中最常用的 QoS 级别之一。

MQTT 的 QoS 2(Quality of Service Level 2) 是最高级别的服务质量,提供 “恰好一次”(Exactly once) 的消息传递语义。

这意味着:

无论网络如何波动、重传多少次,接收方最终只会处理该消息一次,既不会丢失,也不会重复。

这是通过一个 四步握手协议(four-step handshake) 实现的,确保端到端的唯一交付。下面我们从原理、流程、实现细节和适用场景全面解析 QoS 2。


✅QoS 2 

  • 保证送达:消息一定会被接收。
  • 禁止重复:即使在网络异常、ACK 丢失等情况下,也只处理一次
  • 交付次数 = 1 → “Exactly once”
  • 开销最大:需要 4 条 MQTT 控制报文完成一次传输。

⚠️ 注意:QoS 2 的“恰好一次”是 在单个会话(Session)内、针对同一个 Packet ID 而言的。如果客户端断开重连且 Clean Session = true,则历史状态丢失,无法跨会话保证。


底层实现机制:四步握手(Four-Step Handshake)

QoS 2 使用 两个阶段的确认机制,涉及以下四种报文:

步骤发送方 → 接收方作用
1PUBLISH (QoS=2, DUP=0, PID=X)发起消息传输
2PUBREC (PID=X)接收方确认已收到,请求进入第二阶段
3PUBREL (PID=X)发送方确认可以释放消息
4PUBCOMP (PID=X)接收方最终确认,完成交付

这个过程类似于 两阶段提交(2PC),确保双方都达成一致。


1、详细交互流程(以 Client → Broker 为例)

假设客户端 A 向 Broker 发送一条 QoS 2 消息(Packet ID = 100):

[Client A]                     [Broker]|                              ||--- PUBLISH (QoS=2, PID=100) ->|  // Step 1|                              ||<-- PUBREC (PID=100) ---------|  // Step 2:Broker 收到并暂存|                              ||--- PUBREL (PID=100) -------->|  // Step 3:Client 允许 Broker 处理|                              ||<-- PUBCOMP (PID=100) --------|  // Step 4:Broker 确认处理完成|                              |✅ 消息“恰好一次”交付成功
2、关键状态管理:
  • 发送方(Client)
    • 发出 PUBLISH 后,必须保存该消息,直到收到 PUBCOMP。
    • 收到 PUBREC 后,可丢弃原始 PUBLISH 内容,但需记住 PID 已进入第二阶段。
  • 接收方(Broker)
    • 收到 PUBLISH 后,不能立即投递给订阅者,而是先持久化并回复 PUBREC。
    • 只有收到 PUBREL 后,才将消息投递出去,并回复 PUBCOMP。

💡 这种设计防止了因 ACK 丢失导致的重复处理。

3、如何防止重复?

QoS 2 通过 状态机 + Packet ID 去重 实现唯一性:

  1. 接收方维护“已接收但未完成”的 PUBLISH 列表(基于 PID)。
  2. 如果收到重复的 PUBLISH(DUP=1 或相同 PID),直接回复 PUBREC(不重新处理)。
  3. 只有在收到 PUBREL 后,才真正“消费”该消息,并标记为已完成。
  4. 已完成的 PID 在会话中不再接受。

因此,即使网络闪断、重传多次,消息逻辑上只被处理一次


端到端 QoS 与逐跳特性

和 QoS 1 一样,MQTT 的 QoS 是 逐跳(hop-by-hop) 的:

  • 发布者 → Broker:使用发布时指定的 QoS(如 QoS 2)
  • Broker → 订阅者:使用 min(发布QoS, 订阅QoS)

❗ 所以,要实现端到端的 QoS 2,必须:

  • 发布者用 QoS 2 发布
  • 订阅者用 QoS 2 订阅
  • Broker 支持 QoS 2(大多数都支持)

否则,中间某一段降级(如订阅者只订 QoS 1),则最终交付只是 QoS 1(至少一次)。


注意事项与局限性

项目说明
性能开销大4 次报文往返,延迟高,带宽占用多
内存/存储要求高双方需缓存未完成的消息状态(PID + payload)
不适用于高频数据如每秒上千条传感器数据,QoS 2 会严重拖慢系统
会话依赖若 Clean Session = true,重连后状态丢失,无法恢复未完成的 QoS 2 流程
并非万能“恰好一次”仅限协议层;若应用层处理失败,仍需业务补偿

总结

QoS 2 通过四步握手协议,在应用层实现了“恰好一次”的消息传递,彻底解决了丢失和重复问题。但它代价高昂,仅推荐用于对数据一致性要求极高的关键业务场景。在大多数物联网应用中,QoS 1 配合幂等处理已足够。

如果你正在设计系统,建议:

  • 默认用 QoS 0(高效)
  • 需要可靠但可去重 → QoS 1 + 幂等
  • 绝对不能重复且不能丢 → QoS 2(慎用)

📊 三种 QoS 对比总结

特性QoS 0QoS 1QoS 2
语义最多一次至少一次恰好一次
是否可能丢失✅ 是❌ 否❌ 否
是否可能重复❌ 否✅ 是❌ 否
报文数量12(PUBLISH + PUBACK)4(PUBLISH → PUBREC → PUBREL → PUBCOMP)
是否使用 Packet ID
适用场景心跳、遥测控制指令、告警支付、订单、计费等关键操作
http://www.dtcms.com/a/577148.html

相关文章:

  • Dify使用02-Dify集成Ollama
  • [免费]基于Python的Flask酒店客房管理系统【论文+源码+SQL脚本】
  • LeetCode 219.存在重复元素2
  • 【CS224N】《深度学习自然语言处理》完整版笔记
  • 广东企业网站建设推荐网站做收录
  • XC7Z020-1CLG484I Xilinx AMD FPGA Zynq-7000 SoC
  • 论文分享 | BARD-GS:基于高斯泼溅的模糊感知动态场景重建
  • FPGA—ZYNQ学习spi(六)
  • 多智能体医疗会诊系统
  • ETCD 压力测试脚本
  • kali的下载和安装【ISO安装】
  • 从标签到数据流:BarTender让“可追溯”更简单
  • 零基础学AI大模型之Embedding与LLM大模型对比全解析
  • 7.游戏逆向-pxxx-TUObjectArray分析
  • web214-web220
  • 通州北苑网站建设程序开发的基本步骤是什么?
  • 专题:2025中国制造业出海与出海品牌社媒影响力洞察报告|附300+份报告PDF、数据、绘图模板汇总下载
  • 【 C/C++ 算法】入门动态规划 ----- 简单多状态 dp 问题》打家劫舍 和 股票买卖问题
  • (114页PPT)华为FusionCloud私有云最佳实践RegionTypeII(附下载方式)
  • 赤壁专业建站公司学做卤味视频网站
  • 3d光学轮廓仪如何局部测量标准台阶?
  • 【数据集+完整源码】水稻病害数据集,yolov8水稻病害检测数据集 6715 张,目标检测水稻识别算法实战训推教程
  • 3D Gaussian Splatting:渲染流程
  • 云原生LVS+Keepalived高可用方案(二)
  • IBM VO 面试经验分享|一场更像“聊天”的正式考核
  • 用单位的服务器做网站关键词优化网站
  • C语言基础开发入门系列(八)C语言指针的理解与实战
  • 如何绑定网站域名解析电商网站模板html
  • 【机器视觉通用检测框架】基于VS2019 C#+VisionPro9.0开发的视觉框架软件,全套源码,开箱即用
  • 智慧交通管理新范式 基于深度学习的城市交通车型识别AI监控系统 车型识别 停车场车型分类系统 高速路车型识别算法