持久会话在 MQTT 中允许客户端在多次连接之间维持其订阅和消息状态。当客户端与 MQTT 代理建立持久会话时,代理会存储客户端的订阅信息以及任何未送达给客户端的消息。这样,如果客户端断开连接并在以后重新连接,就可以无缝恢复通信。
MQTT 代理可以在客户端离线后存储新消息。当客户端重新连接时,代理会将这些消息发送给客户端。MQTT 中的这个功能称为持久会话。
MQTT 客户端在与服务器建立连接时可以设置是否使用持久会话。持久会话会保留一些重要数据,以允许会话在多个网络连接中继续。持久会话有以下三个主要功能:
我们知道,持久会话需要存储一些重要数据以便会话能够恢复。这些数据部分存储在客户端,部分存储在服务器端。
存储在客户端的会话数据:
存储在服务器上的会话数据:
关于QoS的详细说明参考:MQTT中的QoS是什么???
怎样使用 Persistent Session or Clean Session
持久会话或清洁会话?
客户端可以通过在连接到代理时将 cleanSession 标志设置为 False 来启动持久会话。默认情况下,此值设置为 True。
在上述MQTT V3.1.1这个版本中,Clean Session 是一个标志位,用于控制会话状态的生命周期。值为 TRUE(1) 表示在连接时创建一个新的会话,并在客户端断开连接时自动销毁会话。如果值为FALSE(0),则在连接时会尝试重用之前的会话。如果没有对应的会话,则会创建一个新的会话,该会话在客户端断开连接后始终存在。
接下来,我们将使用 Clean Session 并通过开源跨平台 MQTT 5.0 桌面客户端工具 - MQTTX 来演示。
打开 MQTTX 后,点击 New Connection
按钮创建一个 MQTT 连接,如下所示。
创建名为 Subscribe的连接,并将 Clean Session 关闭(即,设为 false),然后点击右上角的Connect
按钮。
在成功连接后订阅 clean_session_false
主题,并将 QoS 设置为 1。
订阅成功后,请点击右上角的 Disconnect
按钮。然后,创建一个名为 Publish
的连接,再次将 MQTT 版本设置为 3.1.1:
右上角点击Connect,在连接成功后向 clean_session_false
主题发布两条 QoS 1 的消息。
然后,选择Subscribe的连接并点击 Connect
按钮连接到服务器。您将成功接收到两条在离线期间发布的消息。
MQTT5.0会话的改进
在 MQTT 5.0 中,Clean Session 被分为 Clean Start 和 Session Expiry Interval。Clean Start 用于指定在连接时是创建新的会话还是尝试重用现有的会话。Session Expiry Interval 用于指定在网络连接断开后会话将保持多长时间。
Clean Start 为 0 表示必须丢弃任何现有的会话,并创建一个新的会话;为 1 表示必须使用与 Client ID 关联的会话来与客户端恢复通信(除非会话不存在)。
会话过期间隔解决了由于 MQTT 3.1.1 中持久会话的永久存在而导致的服务器资源浪费问题。设置为 0 或未设置表示会话在断开连接时过期。设置为大于 0 的值表示在网络连接关闭后会话将保持多少秒。设置为 0xFFFFFFFF
表示会话永远不会过期。
最佳实践
为了使持久会话生效,您需要注意:
retain
标志设置为 True,具有持久会话的客户端将仍然收到该主题发布的所有消息(而不仅仅是最后一条消息)。
下表展示了 QoS、清理会话标志和保留消息标志如何影响接收到的消息:
MQTT 中 Clean Sessions和Perssistent Sessions的常见问题
Q: MQTT 持久会话与非持久会话有何不同?
A: 一个持久会话在 MQTT 中允许客户端在断开连接后保持其会话状态,包括订阅和未送达的消息,从而确保消息的传递并保留客户端的状态。一个非持久会话或清洁会话会在断开连接时丢弃会话状态,要求客户端重新建立订阅,可能会错过断开连接期间发布的消息。在选择持久会话和非持久会话之间时,取决于应用程序对会话连续性和消息持久性的要求。
Q: 使用持久会话在 MQTT 中有哪些好处?
A: 使用持久会话在 MQTT 中可以带来多种好处。它增强了客户端的可靠性、状态保存能力和重连效率。它提供了不间断的消息传递,消除了重复设置任务的需要,并确保消息按顺序传递,从而提高 MQTT 通信的整体质量和稳健性。
Q: 客户端断开连接期间发送的消息在持久会话中会发生什么?
A: 在 MQTT 的持久会话中,客户端断开连接期间发送的消息会被 MQTT 代理存储,并在客户端重新连接时交付。
Q: 客户端如何知道当前会话是恢复的会话?
A: MQTT 协议从 v3.1.1 版本开始为 CONNACK 消息设计了一个 Session Present 字段。当服务器返回该字段值为 1 时,表示当前连接将使用服务器保存的会话。客户端可以使用该字段值来决定在连接成功后是否重新订阅。
Q: 代理可以排队多少条消息?
A: 代理将消息存储在主内存(RAM)中。因此,代理可以存储的最大消息数量取决于主内存。例如:Mosquitto 默认存储最多 100 条消息。这个设置可以更改。
Q: MQTT 是如何处理持久会话的重新建立的?
A: 如果客户端断开连接然后使用“clean session”标志设置为 false 和相同的 ClientID 重新连接到代理,会话将被恢复。代理将交付其存储的任何消息,客户端可以继续发送任何未确认的出站消息。由于代理已维护订阅,客户端无需再次订阅主题。
Q: 在不稳定网络条件下,MQTT 是如何处理消息传递和会话恢复的?
A: MQTT 提供了三种消息传递质量等级(QoS),QoS 0(最多一次),QoS 1(至少一次),QoS 2(精确一次)。在网络故障情况下,MQTT 提供了一种机制来存储会话信息并通过持久会话从中断中恢复。
Q: 我能否配置会话保持由代理维护的时间长度?
A: 具体的消息队列 telemetry 协议(MQTT)代理可能会实现自己的会话过期策略,这可以超出标准 MQTT 协议的范围。例如,一些代理可能允许你在客户端断开连接期间配置一个会话过期间隔,在此期间会话仍然会被维护。
Q: MQTT 是如何处理多个客户端尝试使用相同的客户端 ID 建立持久会话的情况的?
A: 如果第二个客户端使用与已连接客户端相同的 Client ID 连接到代理,代理必须断开首先连接的客户端。新客户端随后将接管该 Client ID 及其关联的会话。然而,如果客户端使用与之前连接但当前未连接的客户端相同的 Client ID 连接到代理,新客户端将接管与该 Client ID 关联的会话,前提是该会话是持久会话。
Q: 当客户端的持久会话消息队列限制达到上限时会发生什么?
A: 当消息队列限制达到时的具体行为取决于特定的 MQTT 代理实现及其配置的策略。例如,代理可能会丢弃旧消息、丢弃新消息,或者断开客户端连接。
Q: 持久会话和自定义消息队列行为是否有可配置的参数或选项?
A: 是的,MQTT 代理通常允许配置与消息队列相关的某些参数,尽管这在不同的代理实现中可能会有所不同。可配置的参数可能包括最大队列大小、消息保留策略、会话过期间隔、最大报文大小和最大 QoS 级别。
Q: 持久会话中消息队列的大小如何影响代理的内存和处理资源?
A: 在 MQTT 代理中,每个客户端的消息队列(对于持久会话)存储在代理的内存中。这些内存用于保存尚未交付给客户端的消息,或者由于其 QoS 级别而保留以供将来交付的消息。因此,这些消息队列的大小直接影响代理的内存使用情况。
Q: MQTT 在持久会话的消息队列中如何处理超大消息?
A: MQTT 通过使用可配置参数最大包大小(Maximum Packet Size)来处理消息队列中的大消息。
参考链接:
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有