MQTT-消息质量等级

kk3TWT Lv4

简介

MQTT基于TCP/IP协议。但在实际生产过程中,MQTT终端(一般为消息发布者PUBLISHER)所在的网络环境通常是不稳定的。这就导致终端向Broker发送消息的进程会因为网络波动而中断,进而导致信息发送不完全。

为了应对网络波动的问题,MQTT引入了QOS(消息质量等级)。QOS的常见取值与对应的含义如下:

  • QOS=0:消息最多送达一次(消息可能因为网络波动而丢失)
  • QOS=1:消息至少送达一次(消息不会丢失,但是可能会重复发送消息)
  • QOS=2:消息发送且仅送达一次(消息不会丢失,且不会重复发送消息)

发布者在发布消息时可以指定QOS,Broker通常会根据收到消息的QOS,按要求将消息发送给订阅者(如指定QOS=1,那么该消息就会至少发送一次)。

但如果订阅者指定了消息的 最大QOS,则Broker在给订阅者发送消息时,QOS可能会发生改变(如指定最大QOS=1,而发布者发布的消息的QOS=2,那么Broker在向订阅者发送消息时,就会将消息降级,将QOS降低为1)

消息发送流程

QOS=0

QOS=0时,发布的消息即发即弃,不需要等待接收端确认,也不需要存储或重传。这时在接收端不会收到重复信息。

此时,消息发布完全依赖TCP/IP协议,如果网络状况良好,那么消息将顺利发布并接收,否则消息会因为网络波动而无法被接收,进而导致消息的丢失

QOS=1

QOS=1时,引入了应答与重传机制。发布者会缓存 publish 报文,并在发布的报文中添加一个标识报文的 Packet ID 。

而接收者在收到报文后,会发送一个 puback 报文,并返回收到的 Package ID 。

如果发布者收到了 puback 报文(即确认消息送达),那么缓存中的 publish 报文将被删除,否则 publish 报文将被重新发送。

发布者在确认 publish 报文送达后,会将该报文的 Packet ID 标记为可用,并在此后发送的某个报文中复用这个 ID。

产生重复报文的原因

一般而言,发布者重传 publish 报文有两个原因:

  1. 上一条 publish 报文未送达
  2. 上一条 publish 报文已送达,但是在规定时间内发布者没有收到 puback 报文

其中第二条原因会导致重复消息的产生。

又因为在保证报文送达后,发布者将在其他报文上复用使用过的 Packet ID,所以接收端无法通过 Packet ID 对报文进行去重(也就是说,接收端无法通过收到报文的 Pactet ID 分辨出该报文是新的报文还是重传的报文)

QOS=2

QOS=2时,会在应答与重传机制的基础上,增加去重机制。

发布者与接收者使用 pubrec 报文实现应答与 publish 报文的重传(流程与QOS=1时相同)

发布者在确认 publish 报文送达后,会将该报文的 Packet ID 标记为不可用,也就是不在此后的报文中复用这个 ID。

然后发布者会发送 pubrel 报文,告诉接收者需要将刚刚发送的报文中的 Packet ID 标记为可用(也就是释放 ID)。

接收者收到 pubrel 后会返回 pubcomp 报文,向发布者确认释放 ID 的操作

发布者收到返回的 pubcomp 报文后,才会将报文的 Packet ID 标记为可用,并在此后发送的某个报文中复用这个 ID。

不产生重复报文的原因

QOS=2报文的发送可以分为两个阶段:重传阶段和去重阶段

在重传阶段,发布者会与QOS=1时一样,与接收者进行应答与 publish 报文的重传,确认报文送达后就进入去重阶段。

在去重阶段,发布者会告诉接收者,刚刚送达的 publish 报文所使用的 Packet ID 将被用于新的报文。

这样接收者就可以通过收到报文的 Packet ID 分辨出该报文是重传的报文还是新的报文,自然就能够排除重复的报文。

不同取值的应用场景

  • QOS=0:用于传输一些高频且重要程度低的数据(如传感器数据)
  • QOS=1:用于传输一些重要程度较高的数据(如指令),但是由于重复信息的存在,可能会产生无法接受的结果(如给远控电灯发送关灯指令,实际上电灯在开关数次后才关闭)
  • QOS=2:在传输重要程度较高的数据,且能够接受去重过程带来的额外系统开销时使用,通常在金融和航空等行业中应用
  • 标题: MQTT-消息质量等级
  • 作者: kk3TWT
  • 创建于 : 2026-05-16 21:57:25
  • 更新于 : 2026-05-16 22:05:15
  • 链接: https://kk-is-very-happy.top/posts/6cdb0086/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。