【第二章09】MQTT会话

📅 2026/7/31 22:43:11 👁️ 阅读次数 📝 编程学习
【第二章09】MQTT会话

MQTT 会话是 MQTT 协议中用于维持客户端与服务端之间通信状态的核心机制,它不局限于网络连接存活的时间段内,还可以在客户端和服务端的多次连续网络连接之间延续,以此保障网络波动场景下的通信连续性,避免消息丢失、重复订阅等问题。

了解会话

核心作用

避免网络中断后客户端需要重复订阅主题的额外开销,重连后可直接恢复之前的订阅关系
缓存客户端离线期间发布的符合要求的消息,客户端重连后可自动接收这些离线消息
保障 QoS 1、QoS 2 级别的消息在网络异常场景下的可靠交付,不会因为连接断开丢失传输状态
会话存储的核心数据
会话状态由客户端和服务端共同维护:
客户端侧‌:记录已发送到服务端但未完成确认的 QoS 1、QoS 2 消息,以及已从服务端接收但未完成确认的 QoS 2 消息
服务端侧‌:记录客户端的订阅信息、未送达的 QoS 1/QoS 2 消息、已发送但未确认的消息,以及遗愿消息、遗愿延迟间隔等附加状态

关键配置参数

不同 MQTT 版本的会话配置逻辑有明显区别:
MQTT 3.1.1 版本‌
仅通过 Clean Session 标志位控制会话生命周期:
Clean Session = true:会话生命周期和网络连接完全绑定,连接断开后所有会话数据立即销毁,属于非持久会话
Clean Session = false:创建持久会话,连接断开后服务端会保留会话状态,多数实现中默认最长保留3天
MQTT 5.0 版本‌
将会话控制拆分为两个独立参数,灵活性大幅提升:
Clean Start:取值为0时,服务端会尝试恢复该客户端ID对应的历史会话;取值为1时,直接丢弃所有历史会话,创建全新会话
Session Expiry Interval:精确控制连接断开后会话的保留时长,单位为秒:设置为0时连接断开会话立即销毁;设置为大于0的数值时,会话会在断开对应时长后过期销毁;设置为最大值0xFFFFFFFF时,会话永久不过期

两种典型会话类型

临时会话‌
会话状态完全存储在服务端内存中,拥有极高的吞吐量和极低的分发延迟,但服务端节点重启后会话数据会全部丢失,适合不需要保留历史状态、追求低延迟的场景。
持久会话‌
服务端会将会话状态和消息持久化存储到磁盘,还可通过集群副本实现数据冗余,即使服务端节点重启也能完整恢复会话,大幅提升系统可靠性,适合对消息不丢有强要求的物联网场景。

常见使用场景

移动端智能家居、即时通讯类应用:设置较长的会话保留时长,用户App后台断网重连后可直接接收离线期间的通知,无需重新订阅
批量OTA固件升级场景:设备可能处于断网、重启状态,持久会话可以保证设备上线后自动收到升级指令,无需运维人员反复重发
低功耗水表、燃气表类设备:设置会话立即过期,设备断连后不保留无用状态,节省服务端资源
实时数据看板类设备:使用非持久会话,仅关注当前实时数据,不需要接收历史离线消息

会话演示(为离线客户端缓存消息)

先关闭自动恢复订阅功能

新疆一个订阅的客户端


假设订阅一个topic(test/a)

发布者客户端打开,向topic(test/a)发送消息


断开订阅客户端:

依旧向topic(test/a)发送了2条消息

我们讲订阅者这边的clean start设置为0 会话设置永不过期,看看是不是能够延续之前的会话,接收到前面发布的2条消息

结果发现获取到了发布的消息

Topic:test/aQoS:0{"msg":"hello world wellcome"}
Topic:test/aQoS:0{"msg":"hello world wellcome to you"}

总结:MQTT 会话可以为离线客户端缓存消息的能力

MQTT 会话是怎么为离线客户端缓存消息的

MQTT 会话为离线客户端缓存消息,核心是依托‌持久会话机制‌实现的,只有提前配置了持久会话的客户端,服务端才会在其离线期间保留订阅关系、缓存符合规则的消息,待客户端重连后自动推送,完整的缓存流程和细节可以拆解为以下几个部分:

一、缓存生效的前置条件

服务端不会默认对所有客户端开启离线消息缓存,必须同时满足几个核心规则,缓存逻辑才会启动:
‌会话模式配置正确‌
MQTT 3.1.1 版本中,客户端连接时必须将 Clean Session 设置为 false,告知服务端在连接断开后不要销毁会话状态
MQTT 5.0 版本中,客户端需要将 Clean Start 设置为 false,同时配置非0的 Session Expiry Interval,指定会话断开后的保留时长,避免会话被提前回收
‌订阅与发布的消息等级达标‌
客户端必须以 QoS 1 或 QoS 2 等级订阅目标主题,同时发布方也以 QoS 1 或 QoS 2 等级发布消息,服务端才会将这类消息纳入离线缓存队列;QoS 0 等级的消息默认不做离线缓存,仅部分服务端支持可选缓存配置
‌客户端标识唯一‌
服务端通过客户端的 Client ID 唯一识别对应会话,必须保证同一客户端的标识全程不变,否则无法关联到历史缓存的离线消息

二、服务端的缓存存储逻辑

当客户端离线后,服务端会基于已保存的持久会话状态,完成消息的识别和存储:
首先依托会话中留存的客户端订阅列表,识别所有该客户端关注的主题,当有新消息发布到这些主题时,直接将消息写入该客户端专属的离线消息队列
缓存的内容不仅包含离线期间新产生的消息,还会同步保留此前客户端在线时,已经发送但未完成确认的 QoS 1/QoS 2 消息,以及预先配置的遗愿消息
存储模式分为两类:临时会话将消息暂存在内存中,读写速度快但服务端重启后数据会丢失;持久化存储会将会话元数据和离线消息写入磁盘,甚至通过集群副本实现冗余,即使服务节点重启也不会丢失缓存内容,仅会带来轻微的延迟提升

三、缓存的生命周期管理

离线消息的缓存不会永久保留,会严格跟随会话的生命周期执行回收逻辑:
MQTT 3.1.1 版本中,默认在客户端断开连接后,会话和对应的离线消息最多保留3天,超时后自动全部回收
MQTT 5.0 版本中,完全由客户端配置的 Session Expiry Interval 决定缓存时长,设置为0时连接断开缓存立即销毁,设置为最大值时会话和消息可永久保留
当缓存队列达到服务端预设的长度上限时,会按照配置的溢出策略丢弃旧消息,优先保留最新的离线消息,避免占用过多系统资源

四、客户端重连后的推送流程

当客户端重新建立连接时,服务端会先校验客户端标识,匹配到对应的历史持久会话后,直接返回 Session Present 标识告知客户端会话已恢复,无需重新发起主题订阅,随后立即将队列中所有缓存的离线消息,按照预设的 QoS 等级依次推送给客户端,推送完成后同步更新消费进度,后续继续正常转发实时消息。