MQTT会话

为什么需要会话

​ 假如有以下场景,客户端A发送消息到服务端,服务端转发给客户端B,如果这个时候服务端和客户端B的网络连接断开,那么就无法保证消息到达,并且客户端A不知道B连接断开,还会继续发送消息,消息到达服务端之后会因为没有订阅者被丢弃,后面如果客户端B和服务端重新进行连接,但是还需要重新订阅进行正常通信

​ 根据以上的场景,问题的关键在于服务端和客户端中已经发送但是没有完全确认的消息和等待发送的消息以及客户端订阅信息等,这些重要的信息不应该随着断开而消息,我们应该把这些重要信息存储下来,并独立于连接存在,以此引出了会话的作用和意义

什么是会话

​ 会话是MQTT通信的基础,当客户端和服务端建立MQTT连接,他们就创建了一个有状态的会话,后续消息的收发都会在这个会话上进行,消息的发送进度,待发送的消息列表,都属于会话状态的一部分

会话的生命周期

会话的生命周期根据连接和断开分为以下几种

  • 会话生命周期与网络连接相同

我们可以让会话仅持续和网络连接一样长的时间,这表示会话状态将在网络断开的时候被丢弃,下次连接时,必须创建一个新的会话

  • 会话生命周期长于网络连接

可以使会话跨越多个网络连接存在,这就要去客户端和服务端断开连接的时候,必须保存各自的会话状态,比如发送没有完全确认的消息等,以便下次连接时通过会话状态恢复通信,我们把这个会话称为持久会话

恢复会话

为了确保双方能够从正确的会话中恢复通信,服务端和和客户端需要把Client ID 唯一标志进行关联

MQTT为服务端和客户端分别定义了他们需要存储的会话状态

服务端存储的会话状态:

  1. 客户端的订阅信息:客户端只要在会话过期前重连,就不用再重新订阅,因为订阅仍然存在,即便客户端离线状态,服务端也可以给客户端缓存后续到达的消息

  2. 已发送但还未完成确认的 QoS 1和QoS 2的消息以及等待发送的QoS 0、1、2的消息:既包含了上一次连接没来得及下发的消息,也包含了离线期间新到达的消息, QoS 0 的消息,协议没有强制要求,可以存储也可以补存储,可以提供选项自定义是否需要存储

  3. 从客户端收到的还没有完成确认的QoS 2 消息:以便重新连接后QoS2的传输流程能够正常恢复

  4. 遗嘱消息和遗嘱延迟间隔:这里是协议mqtt3.1.1和5.0版本的不同,如果是3.1.1中断开连接遗嘱消息会立即下发,则不需要服务端存储

  5. 会话是否存在:如果断开连接的时间太长,会话可能过期,也可能因为其他故障导致的会话丢失,所以需要服务端保存会话是否存在的信息,客户端连接服务端时,服务端会使用连接报文中的 Client ID 来寻找对应的会话状态,然后通过响应报文中的 Session Persent字段来告诉客户端是否复用了之前的会话,以便两端在一个正确的基础上进行通信

客户端需要存储的会话状态:

  • 所有发送给服务端但是还没有完成确认的QoS1和2消息以及从服务端收到的没有确认的QoS2的消息,原理和服务端状基本类似,不再赘述
不同协议版本中的会话字段

MQTT 5.0会话字段

Clean Start字段

用于表示是否在连接时复用已经存在的会话

  • Clean Start = 0 ,表示尝试从已存在的会话中恢复通信,客户端连接时,如果服务端中存在与指定client id关联的会话,服务端就必须基于这个会话来恢复通信,如果不存在对应的会话,服务端必须创建一个全新的会话
  • Clean Start = 1,不从会话中恢复通信,即便客户端和服务端连接时存在相应的会话,服务端也必须丢弃会话创建一个全新的会话

Session Expiry Interval字段

指定会话在连接断开后能够保留的最长时间,如果过,期时间内客户端没有重新连接,服务端则会丢弃对应的会话状态

  • Session Expiry Interval = 0,生命周期与网络连接相同,会话将在网络连接断开的时候立即结束
  • Session Expiry Interval > 0,如果值大于0,则表示会话将在连接断开后多少秒后过期
  • Session Expiry Interval = 0xFFFFFFFF,表示会话永不过期

每个客户端都可以独立设置自己的Session Expiry Interval ,MQTT允许客户端在断开连接(DISCONNECT)的时候 重新设置过期时间,比如延长会话时间或者直接为0取消持久会话等等

MQTT3.1.1 会话字段

3.1.1协议中只有一个Clean Session字段

Clean Session字段

  • Clean Session = 0,等同于5.0中 Clean Start = 0 、Session Expiry Interval = 0xFFFFFFFF
  • Clean Session = 1,等同于5.0中 Clean Start = 1 、Session Expiry Interval = 0

3.1.1协议的的灵活性不如5.0,在3.1.1协议中,不能为每个客户端设置单独的会话时间 也不能断开时重新设置过期时间,导致不需要会话保留很久的客户端,会话信息也回被服务端长时间存储,也造成一定程度上服务端资源的浪费

如何选择会话的生命周期

选择持久会话的场景
  • 不希望错误离线期间的消息
  • 不希望QoS 1 和QoS 2消息丢失
  • 不希望每次连接都重新建立订阅
  • 设备定期休眠,不希望长时间维护连接
选择非持久会话的场景
  • 只对外发布 QoS 0的消息,不会接收任何消息
  • 只订阅QoS 0 的消息,不关心离线期间的消息

MQTT-会话的更多相关文章

  1. MQTT控制---connect

    连接服务端 客户端到服务端的第一个报文必须是CONNECT,且只能发送一次,发送的第二个connect报文当作违规处理并断开连接. 有效载荷包含一个或者多个编码的字段.包括客户端的唯一标识符,Will ...

  2. MQTT协议及EMQ应用

    MQTT是基于TCP/IP协议栈构建的异步通信消息协议,是一种轻量级的发布/订阅信息传输协议.MQTT在时间和空间上,将消息发送者与接受者分离,可以在不可靠的网络环境中进行扩展.适用于设备硬件存储空间 ...

  3. MQTT 协议学习:004-MQTT建立通信与 CONNECT 、CONNACK 报文

    背景 上一讲 MQTT 协议学习:通信报文的构成介绍了在MQTT通信中,各报文的通信流程:从本讲开始,我们开始介绍实际中使用的报文,以及它们的组成. CONNECT - 连接请求 报文 客户端到服务端 ...

  4. MQTT抓包分析

    1. 概述 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通讯协议,该 ...

  5. EMQ ---v2.3.11源码成熟度

    从原作者那边了解到,总体还可以,但是做不到99.99%稳定.主要是连接内存占用没有保护. pubsub均衡时很稳定,但是集群或大量消息向少量订阅发布时会崩溃,小概率情况. EMQ中CPU是公平分配给M ...

  6. EMQ ---问题集

    1)emqttd 使用 SSL遇到的问题:服务器直接布了一份emqttd ,然后什么都没管,端口默认的ws 8083,wss8084,mqtt 1883,mqtt(ssl) 8883. 结果跑起来之后 ...

  7. EMQ学习笔记---Clean Session和Retained Message

    MQTT会话(Clean Session)MQTT客户端向服务器发起CONNECT请求时,可以通过’Clean Session’标志设置会话.‘Clean Session’设置为0,表示创建一个持久会 ...

  8. MQTT 协议学习: QoS等级 与 会话

    背景 QoS 等级 与 通信的流程有关,直接影响了整个通信.而且篇幅比较长,所以我觉得应该单独拎出来讲一下. 概念 QoS 代表了 服务质量等级. 设置上,由2 位 的二进制控制,且值不允许为 3(0 ...

  9. 几个MQTT的知识点

    开始正文前需要感谢一下网友“小龙”和emqtt.io群里的网友们的帮助,本人刚刚开始使用MQTT有很多不懂的地方,在emqtt.io群里询问解决方法的时候,“小龙”给我详细的讲解了一些MQTT的知识点 ...

  10. 【开源】MQTT推送服务器——zer0MqttServer(Java编写)

    目录 说明 功能 如何使用 参考帮助 说明 重要的放前面:V1.0版本是一个非常基础的版本,除了完整的MQTT协议实现外,其他功能什么都没做. MQTT 协议是 IBM 开发的即时通讯协议,相对于 I ...

随机推荐

  1. 用反证法说明List<Object>和List<String>不存在子父类关系可行吗?

    看宋红康老师的Java基础视频讲解,视频中用反证法证明List

  2. 在VS中使用Wind数据终端API的经验(一)

    因工作需要,使用vs2019来调用Wind金融终端API数据接口.具体步骤按照wind的帮助文档一步步做下来.这里提一下和帮助文档不同的地方. Windows Console APP下,编译项目后出现 ...

  3. Java集合框架个人总结

    Java集合框架个人总结 集合主要分为两大类:①单列集合Collection ②双列集合Map 集合存储的都是引用类型,不可是基础类型,如果保存基础类型需要用包装类. 1.Collection接口 ​ ...

  4. idea导入数据库

    yml文件(在启动项文件(main)里,eg:springbook文件里面) sh-bean里org.example.sh.beans的Category类   CategoryDAO名字要和Categ ...

  5. docker安装pgsql

    aliyun环境docker安装并使用postgres121.拉取postgres镜像docker pull postgres:12 2.检查现有镜像docker images 3.启动postgre ...

  6. 例题1:shell脚本

    题目总结: 1.搜索子域名的shell脚本 2.嗅探并抓去网页快照shell脚本 3.漏洞利用程序下载脚本 题目一:依次输入以下代码即可: 1.wget www.megacorpone.com  2. ...

  7. 讨论django并发能力及提供并发解决方案

    django 的并发能力真的是令人担忧,这里就使用 nginx + uwsgi 提供高并发 nginx 的并发能力超高,单台并发能力过万(这个也不是绝对),在纯静态的 web 服务中更是突出其优越的地 ...

  8. 基于 Istio 的灰度发布架构方案实践之路

    作者:京东物流 赵勇萍 1. 背景介绍 灰度发布,又名金丝雀发布,是指能够平滑过渡的一种发布方式.基于系统稳定性和快速业务迭代的综合考虑,业务应用开发团队采取了新版本服务灰度上线的方式,即新版本服务并 ...

  9. 👋 和我一起学【Three.js】「初级篇」:0. 总论

    「和我一起学 XXX」是我 2023 年的一个新企划,目的是向读者(也包括未来的自己)介绍我正在学习的某项新技术.文章会通过长期反复迭代的方式保持其内容的新鲜度.文章有较大内容更新时,会在文章开头进行 ...

  10. 网络安全(中职组)-B模块:Web隐藏信息获取

    Web隐藏信息获取任务环境说明:服务器场景名:web20200604服务器场景用户名:未知(关闭链接) 1.    通过本地PC中渗透测试平台Kali使用Nmap扫描目标靶机HTTP服务子目录,将扫描 ...