前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MQTT Persistent Session or Clean Session持久会话或清洁会话(附示例)

MQTT Persistent Session or Clean Session持久会话或清洁会话(附示例)

作者头像
Hello工控
发布于 2025-05-17 06:42:54
发布于 2025-05-17 06:42:54
1630
举报
文章被收录于专栏:Hello工控Hello工控
不稳定的网络和有限的硬件资源是物联网应用需要面对的两大问题。由于网络波动和资源限制,MQTT 客户端与代理之间的连接可能会在任何时候异常断开。为了应对网络断开对通信的影响,MQTT 协议提供了持久会话(Persistent Session)。

持久会话在 MQTT 中允许客户端在多次连接之间维持其订阅和消息状态。当客户端与 MQTT 代理建立持久会话时,代理会存储客户端的订阅信息以及任何未送达给客户端的消息。这样,如果客户端断开连接并在以后重新连接,就可以无缝恢复通信。

MQTT持久会话

MQTT 代理可以在客户端离线后存储新消息。当客户端重新连接时,代理会将这些消息发送给客户端。MQTT 中的这个功能称为持久会话

MQTT 客户端在与服务器建立连接时可以设置是否使用持久会话。持久会话会保留一些重要数据,以允许会话在多个网络连接中继续。持久会话有以下三个主要功能:

  • 避免由于网络中断需要重复订阅的额外开销。
  • 避免在离线期间丢失消息。
  • 确保在网络中断期间 QoS 1 和 QoS 2 的消息不受影响。

存储哪些数据以保持持久会话?

我们知道,持久会话需要存储一些重要数据以便会话能够恢复。这些数据部分存储在客户端,部分存储在服务器端。

存储在客户端的会话数据:

  • QoS 1 和 QoS 2 消息已发送到服务器,但尚未完成确认。
  • QoS 2 消息已从服务器接收但尚未完成确认。

存储在服务器上的会话数据:

  • 会话是否存在,即使会话状态的其余部分为空。
  • QoS 1 和 QoS 2 消息已发送给客户端但尚未完成确认。
  • QoS 0 消息(可选),QoS 1 和 QoS 2 等待发送给客户端的消息。
  • QoS 2 消息已从客户端接收但尚未完成确认,遗愿消息,遗愿延迟间隔。

关于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 表示会话永远不会过期。

最佳实践

为了使持久会话生效,您需要注意:

  • 代理使用客户端 ID 来识别持久会话中的客户端。因此,请确保为每个客户端使用唯一的客户端 ID。
  • 您需要以 QoS 级别 1 或 2 订阅主题。只有这样,代理才会发布未送达的消息。
  • 消息还必须以 QoS 级别 1 或 2 的形式发布到该主题。如果客户端以 QoS 级别 0 发布消息,代理将不会存储这些消息。
  • 如果发布消息时 retain 标志设置为 True,具有持久会话的客户端将仍然收到该主题发布的所有消息(而不仅仅是最后一条消息)。 下表展示了 QoS、清理会话标志和保留消息标志如何影响接收到的消息:
  • 根据服务器性能、网络条件和客户端类型适当评估会话过期时间。设置得太长会占用更多的服务器资源。设置得太短则会导致会话在成功重新连接之前过期。
  • 当客户端确定会话不再需要时,可以使用 Clean Session 为 true 重新连接,然后在成功重新连接后断开连接。在 MQTT 5.0 中,断开连接时可以直接将 Session Expiry Interval 设置为 0,表示会话将在断开连接时过期。

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)来处理消息队列中的大消息。

参考链接:

  1. http://www.steves-internet-guide.com/mqtt-clean-sessions-example/
  2. https://www.emqx.com/en/blog/mqtt-session
  3. https://www.hivemq.com/blog/mqtt-essentials-part-7-persistent-session-queuing-messages/
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hello工控 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MQTT持久会话
  • 存储哪些数据以保持持久会话?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档