MQTT 消息队列遥测传输协议 QoS Quality of Service 消息传输的服务质量 对一个消费者客户端建立TCP连接后是否关心之前状态的定义
MQTT - The Standard for IoT Messaging https://mqtt.org/
什么是 MQTT?- MQTT 协议简介 - AWS https://aws.amazon.com/cn/what-is/mqtt/
MQTT 协议背后的历史是什么?
MQTT 协议于 1999 年发明,用于石油和天然气行业。工程师需要一种协议来实现最小带宽和最小电池损耗,以通过卫星监控石油管道。最初,该协议被称为消息队列遥测传输,得名于首先支持其初始阶段的 IBM 产品 MQ 系列。2010 年,IBM 发布了 MQTT 3.1 作为任何人都可以实施的免费开放协议,然后于 2013 年将其提交给结构化信息标准促进组织 (OASIS) 规范机构进行维护。2019 年,OASIS 发布了升级的 MQTT 版本 5。现在 MQTT 不再是首字母缩写词,而是被认为是协议的正式名称。
MQTT 背后的原理是什么?
MQTT 协议基于发布/订阅模型工作。在传统的网络通信中,客户端和服务器直接相互通信。客户端向服务器请求资源或数据,然后,服务器将处理并发回响应。但是,MQTT 使用发布/订阅模式将消息发送者(发布者)与消息接收者(订阅者)解耦。相反,称为消息代理的第三个组件将处理发布者和订阅者之间的通信。代理的工作是筛选所有来自发布者的传入消息,并将它们正确地分发给订阅者。代理将发布者和订阅者解耦,如下所示:
空间解耦
发布者和订阅者不知道彼此的网络位置,也不交换 IP 地址或端口号等信息。
时间解耦
发布者和订阅者不会同时运行或具有网络连接。
同步解耦
发布者和订阅者都可以发送或接收消息,而不会互相干扰。例如,订阅者不必等待发布者发送消息。
https://eclipse.dev/paho/files/mqttdoc/MQTTClient/html/pubsync.html
Paho MQTT C Client Library: MQTT Client library for C https://eclipse.dev/paho/files/mqttdoc/MQTTClient/html/index.html
云消息队列MQTT版如何收费_云消息队列 MQTT 版(MQTT)-阿里云帮助中心 https://help.aliyun.com/zh/apsaramq-for-mqtt/product-overview/billing-overview
微消息队列MQTT版的基本概念有哪些_云消息队列 MQTT 版(MQTT)-阿里云帮助中心 https://help.aliyun.com/zh/apsaramq-for-mqtt/product-overview/service-introduction-terms?spm=a2c4g.11186623.0.i0#concept-42420-zh
QoS
QoS(Quality of Service)指消息传输的服务质量。分别可在消息发送端和消息消费端设置。
发送端的QoS设置:影响发送端发送消息到云消息队列 MQTT 版的传输质量。
消费端的QoS设置:影响云消息队列 MQTT 版服务端投递消息到消费端的传输质量。
QoS包括以下级别:
QoS0:代表最多分发一次。
QoS1:代表至少达到一次。
QoS2:代表仅分发一次。
cleanSession
cleanSession标志是MQTT协议中对一个消费者客户端建立TCP连接后是否关心之前状态的定义,与消息发送端的设置无关。具体语义如下:
cleanSession=true:消费者客户端再次上线时,将不再关心之前所有的订阅关系以及离线消息。
cleanSession=false:消费者客户端再次上线时,还需要处理之前的离线消息,而之前的订阅关系也会持续生效。
QoS和cleanSession搭配使用时需注意以下几点:
MQTT要求每个客户端每次连接时的cleanSession标志必须固定,不允许动态变化,否则会导致离线消息的判断有误。
MQTT目前对外QoS2消息不支持非cleanSession,如果客户端以QoS2方式订阅消息,即使设置cleanSession=false也不会生效。
P2P消息的cleanSession判断以接收方客户端的配置为准。
消费端QoS和cleanSession的不同组合产生的结果如QoS和cleanSession的组合关系所示。
消息收发TPS:指每秒钟使用微消息队列支持的协议,进行上行数据发送和下行数据接收的消息总条数。
计算规则参考链接 >>
表 1. QoS和cleanSession的组合关系
QoS级别
cleanSession=true
cleanSession=false
QoS0
无离线消息,在线消息只尝试推一次。
无离线消息,在线消息只尝试推一次。
QoS1
无离线消息,在线消息保证可达。
有离线消息,所有消息保证可达。
QoS2
无离线消息,在线消息保证可达且只接收一次。
暂不支持。
计价倍率
在使用MQTT协议传输消息时,QoS和cleanSession参数的设置会影响实际的计费。每条消息(包含客户端和云端API的调用请求)以1为基本计价单位,针对具体协议中的特定传输质量,需要乘以相应的倍率。
云消息队列 MQTT 版消息的计价倍率如下表所示。
传输质量级别
计价倍率
MQTT协议QoS=0且cleanSession=true
1
MQTT协议QoS=0且cleanSession=false
1
MQTT协议QoS=1且cleanSession=true
2
MQTT协议QoS=1且cleanSession=false
5
MQTT协议QoS=2且cleanSession=true
5
close
Too many message! Tps limit!
使用MQTT的设备查询功能排查设备离线问题_云消息队列 MQTT 版(MQTT)-阿里云帮助中心 https://help.aliyun.com/zh/apsaramq-for-mqtt/user-guide/query-the-connection-history-of-a-device
字段 |
说明 |
Channel ID |
设备连接标识。 |
设备动作 |
|
动作说明 |
|
时间 |
设备动作发生的时间。 |
Frame 2373: 108 bytes on wire (864 bits), 108 bytes captured (864 bits) on interface \Device\NPF_{55D98F70-7C98-4098-BDBE-3EBD18C3AAAA}, id 0
Ethernet II, Src: HonHaiPrecis_03:30:0d (f4:6b:8c:03:30:0d), Dst: NewH3CTechno_0b:2d:60 (a0:69:d9:0b:2d:60)
Internet Protocol Version 4, Src: 192.100.1.113, Dst: 47.112.223.225
Transmission Control Protocol, Src Port: 58177, Dst Port: 1883, Seq: 1, Ack: 1, Len: 54
Source Port: 58177
Destination Port: 1883
[Stream index: 70]
[Conversation completeness: Complete, WITH_DATA (47)]
[TCP Segment Len: 54]
Sequence Number: 1 (relative sequence number)
Sequence Number (raw): 4180832046
[Next Sequence Number: 55 (relative sequence number)]
Acknowledgment Number: 1 (relative ack number)
Acknowledgment number (raw): 4133711472
0101 .... = Header Length: 20 bytes (5)
Flags: 0x018 (PSH, ACK)
Window: 516
[Calculated window size: 132096]
[Window size scaling factor: 256]
Checksum: 0xd177 [unverified]
[Checksum Status: Unverified]
Urgent Pointer: 0
[Timestamps]
[SEQ/ACK analysis]
TCP payload (54 bytes)
[PDU Size: 54]
MQ Telemetry Transport Protocol, Connect Command
Header Flags: 0x10, Message Type: Connect Command
Msg Len: 52
Protocol Name Length: 4
Protocol Name: MQTT
Version: MQTT v3.1.1 (4)
Connect Flags: 0xc0, User Name Flag, Password Flag, QoS Level: At most once delivery (Fire and Forget)
1... .... = User Name Flag: Set
.1.. .... = Password Flag: Set
..0. .... = Will Retain: Not set
...0 0... = QoS Level: At most once delivery (Fire and Forget) (0)
.... .0.. = Will Flag: Not set
.... ..0. = Clean Session Flag: Not set
.... ...0 = (Reserved): Not set
Keep Alive: 30
Client ID Length: 28
Client ID: GID_one_topic_dev_sub@123sub
User Name Length: 4
User Name: u123
Password Length: 4
Password: p123
MQ Telemetry Transport Protocol, Connect Ack
Header Flags: 0x20, Message Type: Connect Ack
Msg Len: 2
Acknowledge Flags: 0x00
Return Code: Connection Accepted (0)
Frame 4037597: 890 bytes on wire (7120 bits), 890 bytes captured (7120 bits) on interface \Device\NPF_{55D98F70-7C98-4098-BDBE-3EBD18C3AAAA}, id 0
Ethernet II, Src: NewH3CTechno_0b:2d:60 (a0:69:d9:0b:2d:60), Dst: HonHaiPrecis_03:30:0d (f4:6b:8c:03:30:0d)
Internet Protocol Version 4, Src: 47.112.223.225, Dst: 192.100.1.113
Transmission Control Protocol, Src Port: 1883, Dst Port: 56446, Seq: 9650622, Ack: 538, Len: 836
Source Port: 1883
Destination Port: 56446
[Stream index: 2659]
[Conversation completeness: Incomplete, DATA (15)]
[TCP Segment Len: 836]
Sequence Number: 9650622 (relative sequence number)
Sequence Number (raw): 2062269768
[Next Sequence Number: 9651458 (relative sequence number)]
Acknowledgment Number: 538 (relative ack number)
Acknowledgment number (raw): 269514131
0101 .... = Header Length: 20 bytes (5)
Flags: 0x018 (PSH, ACK)
Window: 237
[Calculated window size: 30336]
[Window size scaling factor: 128]
Checksum: 0x00cb [unverified]
[Checksum Status: Unverified]
Urgent Pointer: 0
[Timestamps]
[SEQ/ACK analysis]
TCP payload (836 bytes)
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
[PDU Size: 38]
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
0011 .... = Message Type: Publish Message (3)
.... 0... = DUP Flag: Not set
.... .00. = QoS Level: At most once delivery (Fire and Forget) (0)
.... ...0 = Retain: Not set
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
MQ Telemetry Transport Protocol, Publish Message
Header Flags: 0x30, Message Type: Publish Message, QoS Level: At most once delivery (Fire and Forget)
Msg Len: 36
Topic Length: 13
Topic: test_topic
Message: 312331373034323630353738233132332332332e39
扫盲贴:认识MQTT通信协议-推送开发/专项技术区 - 即时通讯开发者社区! http://www.52im.net/forum.php?mod=viewthread&tid=318&ctid=18
MQTT特点
MQTT协议是为大量计算能力有限,且工作在低带宽、不可靠的网络的远程传感器和控制设备通讯而设计的协议。
它具有以下主要的几项特性:
1、使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合:
这一点很类似于XMPP,但是MQTT的信息冗余远小于XMPP(因为XMPP使用的是XML这种格式来传递数据,你懂的)。
2、对负载内容屏蔽的消息传输。
3、使用TCP/IP提供网络连接:
主流的MQTT是基于TCP连接进行数据推送的,但是同样有基于UDP的版本,叫做MQTT-SN。这两种版本由于基于不同的连接方式,优缺点自然也就各有不同了。
4、有三种消息发布服务质量:
- “至多一次”,消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复:
这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就收不到了。 - “至少一次”,确保消息到达,但消息重复可能会发生:
这一种方式比较鸡肋,在我的想象中没能想到这种质量的发送在常规的APP开发中有什么用处。 - “只有一次”,确保消息到达一次:
这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到一次。
5、小型传输,开销很小(固定长度的头部是2字节),协议交换最小化,以降低网络流量:
这就是为什么在介绍里说它非常适合“在物联网领域,传感器与服务器的通信,信息的收集”,要知道嵌入式设备的运算能力和带宽都相对薄弱,使用这种协议来传递消息再适合不过了。
6、使用Last Will和Testament特性通知有关各方客户端异常中断的机制:
- Last Will:即遗言机制,用于通知同一主题下的其他设备发送遗言的设备已经断开了连接。
- Testament:遗嘱机制,功能类似于Last Will 。
IBM技术经理访谈:MQTT协议的制定历程、发展现状等-推送开发/专项技术区 - 即时通讯开发者社区! http://www.52im.net/forum.php?mod=viewthread&tid=525&ctid=18
在传输协议方面,应用在物联网上的还有ATTP,TCM还有我们的MQTT,那么相对于这些协议,MQTT它的优势在哪?
首先从网络层面来讲,由于它从定制的一开始就是为物联网这个场景所特别经过了一些优化的。所以在各个方面,包括网络的可达性,消息的连通性,以及使用的过程中的能耗等等方面,都是会有优势的。
具体有几个方面:
- 第一点:是它本身是特别轻量级的,我们知道嵌入式设备的计算能力,往往会比我们传统意义上的像PC要弱很多,那么在一个八位的系统当中,可能我只要30K的空间,就能把相应的MQTT的客户端给跑起来,就可以传输信息了。
- 第二点:就是它本身是为预定义不稳定的网络而设计的一个传输协议。因为我们通常意义上的传输协议都是基于稳定网络的传输的,会专门为了这种稳定的网络去做一些优化,以使传输的效率最高,但是MQTT是正好相反过来,它是预定义为不稳定的网络,这个网络会频繁中断,在这样的情况下设计一个协议,它的最小的传输字节只有两个,以此来保证在非常恶劣的网络条件下,仍然有很好的消息可达率。
- 第三点:是它的消息的交互模式跟传统意义上不太一样,它采用了发布和订阅的模式。这种模式有什么好处呢?就是它除了可以做一对一的消息传输以外也可以做一对多的消息传输,也就是说当数据源发布一条消息的时候,可以有多个接收端同时能收到这个消息,这样对于很多的物联网场景来说,就会变得比较灵活。
- 第四点:就是安全性,虽然它是一个非常轻量级的协议,但是它在客户端到服务器端的JAAS认证,包括在通讯传输层的SSL的加密过程当中,是完全能支持这些安全的特性的,以保证有一些场景如果需要安全的数据传输的话,它也能提供非常好的支持。
- 第五点:就是它提供了多种消息质量的服务,也就是说可以根据场景定义消息或者数据,是最多一次传输,还是最少一次传输,还是只保证有一次传输。那各种不同类型的消息服务有不同的网络开销,在每一个场景下面,MQTT传输和传统的别的通讯方式的传输对比起来,它的能耗一般只是1/4,或者更低
其实MQTT协议从1999年刚刚诞生的时候,只是IBM和几个合作伙伴一起来做事情,大概经过了5年以后,到了2005年,随着互联网的发展,物联网才真正更多的进入了大家的视野。到04年,05年的时候,我们认为MQTT这个协议,可能更多的要以一种更开放的态度来迎接大家的考验,同时也有更大规模的推广,所以在那个时候开放了整个MQTT协议本身的内容,也开放了一个论坛让大家能够参与进来,提供各自的意见,一起帮助这个协议往前。大概又过了五到六年的时间,在11年的时候,我们觉得这个开放程度还不够,我们的故事可能要讲的更公开,更开放一点,所以在那个时间点我们就把手里的所有已经做过的MQTT客户端,所有的内容全部开源了。
在这个过程当中,您刚才问到了,会有什么样的一些技术上的挑战,最主要的还是刚才讲到的就是对于这个协议的在不停的做修正,这些修正最最重要的因素,就是保证它在带宽非常低而且网络特别不稳定的情况下,怎么样能提高它的连接能力,以及提高它数据传输的能力。第二部分,就是对于物联网这样的场景来说,是不是对协议能有进一步的优化。
我可以举个例子,在目前新版MQTT协议里边,有一个功能叫做遗嘱和遗愿,大家听这个名字就觉得还是蛮新鲜的,因为在IT世界里面我们很少有这样一个概念,但是它理解起来也蛮直观的,在协议里面加入这个功能,主要就是因为我们是一个物联化的世界,我们所有设备是成千上万的,并且很多的设备工作在非常不稳定的环境当中,甚至有很多可能都工作在野外环境当中,所以一个设备它连不上网络,或者连不上背后的系统是一个常态,遗嘱和遗愿的机制就是为了保证当一个设备连不上的时候,服务器端有一个专门的机制能够保证马上能够收到消息,这个设备出了什么状况,从而可以有非常快的反馈,这个反馈可以是人工的,也可以是系统自动做出的,对某一个结点做出一些补偿。这些内容,其实就是这个协议适应物联网场景所做出的一些特别挑战。
MQTT 持久会话 vs. Clean Session内幕一网打尽-腾讯云开发者社区-腾讯云 https://cloud.tencent.com/developer/article/2376625
物联网应用两大难题,MQTT 客户端与服务器的连接可能随时因网络波动及资源限制而异常断开。为解决网络连接断开对通信造成的影响,MQTT 协议提供持久会话功能。
MQTT 客户端在发起到服务器的连接时,可设置是否创建一个持久会话。持久会话会保存一些重要数据,以使会话能在多个网络连接中继续。
2 作用
- 避免因网络中断导致需要反复订阅带来的额外开销
- 避免错过离线期间的消息
- 确保 QoS 1 和 QoS 2 的消息质量保证不被网络中断影响
3 持久会话需存储哪些数据?
通过上文我们知道持久会话需要存储一些重要的数据,以使会话能被恢复。这些数据有的存储在客户端,有的则存储在服务端。
客户端中存储的会话数据:
- 已发送给服务端,但是还没有完成确认的 QoS 1 与 QoS 2 消息
- 从服务端收到的,但是还没有完成确认的 QoS 2 消息
服务端中存储的会话数据:
- 会话是否存在,即使会话状态其余部分为空。
- 已发送给客户端,但是还没有完成确认的 QoS 1 与 QoS 2 消息。
- 等待传输给客户端的 QoS 0 消息(可选),QoS 1 与 QoS 2 消息。
- 从客户端收到的,但是还没有完成确认的 QoS 2 消息,遗嘱消息和遗嘱延时间隔。
4 MQTT Clean Session
控制会话状态生命周期的标志位:
true
表示创建一个新的会话,在客户端断开连接时,会话将自动销毁false
表示创建一个持久会话,在客户端断开连接后会话仍然保持,直到会话超时注销
持久会话能被恢复的前提是客户端使用固定 Client ID 再连,如 Client ID 动态,连接成功后将会创建一个新的持久会话。
如下Dashboard,图中连接虽然是断开状态,但因是持久会话,仍能被查看到,且可在 Dashboard 中手动清除该会话:
EMQX 也支持在 Dashboard 设置 Session 相关参数。
MQTT 3.1.1 没规定持久会话何时过期,仅从协议层理解,这持久会话应永久存在。但实际场景不现实,因为它非常占服务端资源,所以服务端实际向用户提供一个全局配置来限制会话过期时间。如设置会话过期时间 5 min,最大消息数为 1000 条,且不保存 QoS 0 消息。
5 使用
打开 MQTTX 后如下所示,点击 New Connection
按钮创建一个 [MQTT 连接]。
创建名为 MQTT_V3
的连接,Clean Session 为关闭状态(即为 false),MQTT 版本选择 3.1.1,然后点击右上角的 Connect
按钮。
连接成功后订阅 clean_session_false
主题,且 QoS 设置为 1。
订阅成功后,点击右上角的断开连接按钮。然后,创建一个名为 MQTT_V3_Publish
的连接,MQTT 版本同样设置为 3.1.1,连接成功后向 clean_session_false
主题发布两条 QoS 1 消息。
然后选中 MQTT_V3 连接,点击连接按钮连接至服务器,将会成功接收到两条离线期间的消息。
6 MQTT 5.0 中的会话改进
MQTT 5.0 中将 Clean Session 拆成:
- Clean Start 指定连接时是创建一个全新的会话还是尝试复用一个已存在的会话
- Session Expiry Interval 指定网络连接断开后会话的过期时间
Clean Start 为 true
时表示必须丢弃任何已存在的会话,并创建一个全新的会话;为 false
时表示必须使用与 Client ID 关联的会话来恢复与客户端的通信(除非会话不存在)。
Session Expiry Interval 解决了 MQTT 3.1.1 中持久会话永久存在造成的服务器资源浪费问题。设置为 0 或未设置,表示断开连接时会话即到期;设置为大于 0 的数值,则表示会话在网络连接关闭后会保持多少秒;设置为 0xFFFFFFFF
表示会话永远不会过期。
7 FAQ
当会话结束后,保留消息还存在么?
[MQTT 保留消息]不是会话状态的一部分,它们不会在会话结束时被删除。
客户端如何知道当前会话是被恢复的会话?
MQTT 协议从 v3.1.1 开始,就为 CONNACK 报文设计了 Session Present 字段。当服务器返回的该字段值为 1 时,表示当前连接将会复用服务器保存的会话。客户端可通过该字段值决定在连接成功后是否需要重新订阅。
使用持久会话的建议
- 不能使用动态 Client ID,需要保证客户端每次连接的 Client ID 都是固定的。
- 根据服务器性能、网络状况、客户端类型等合理评估会话过期时间。设置过长会占用更多的服务端资源,设置过短会导致未重连成功会话就失效。
- 当客户端确定不再需要会话时,可使用 Clean Session 为 true 进行重连,重连成功后再断开连接。如果是 MQTT 5.0 则可在断开连接时直接设置 Session Expiry Interval 为 0,表示连接断开后会话即失效。
8 总结
至此完成对 MQTT 持久会话的介绍,并通过桌面客户端演示了 Clean Session 的使用。读者可参考本文借助 MQTT 持久会话实现离线消息的接收及降低订阅开销。