MQTT-保留消息和遗嘱消息

这篇具有很好参考价值的文章主要介绍了MQTT-保留消息和遗嘱消息。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

遗嘱消息

为什么需要遗嘱消息

       MQTT的订阅发布机制,解耦了消息的发送方和接收方,这使我们没有办法获取对端的状态,为了解决该问题,MQTT提供了遗嘱消息,为意外断线的客户端提供了对外发出通知的能力

如何使用遗嘱消息

       使用遗嘱消息,客户端需要在连接时,也就是connect报文中指定遗嘱消息,除了正常CONNECT报文字段,需要为遗嘱消息提供以下字段

Will Topic #遗嘱消息主题

Will QoS  # 遗嘱消息级别

Will Retain  # 将遗嘱消息设置为保留消息
'''
遗嘱消息一旦发布,就会在服务端的会话状态中删除,不能多次消费,我们不能保证遗嘱消息发出的时候订阅端是否在线,为了避免错过遗嘱消息,可以使用Will Retain = True 字段将遗嘱消息设置为保留消息,这样订阅了该主题的客户端不管什么时候上线,都可以收到另外一方的离线通知
'''

Will Properties # 遗嘱消息属性  ↓

Will Delay Interval #遗嘱消息的属性↑, 设置遗嘱消息的延迟发送时间
'''
在MQTT 5.0中,可以使用 Will Delay Interval 设置延迟发送遗嘱消息,单位是S,如果客户端及时恢复,那么遗嘱消息的发生倒计时就会终止,可以避免客户端在短暂离线后恢复,可以继续服务时但是遗嘱消息已经发出的情况,和保留消息不同的是,遗嘱消息是会话状态的一部分,没有办法存在比会话更长的时间,如果遗嘱延迟时间大于会话过期时间,会话结束的时候遗嘱会立即发布
'''

Will Payload  # 遗嘱消息内容

​ 在客户端连接成功后,遗嘱消息就会存储在服务端中,一旦客户端连接异常断开,服务端就会把遗嘱消息发送给对应的订阅者,如果客户端是正常断开,遗嘱消息则不会发布,在MQTT中,客户端的意外断开可以分为以下几种情况

  • 服务端检测到了一个I/O故障或者网络故障
  • 客户端在心跳的时间内未能通讯
  • 客户端在没有发生Reason Code 为0的DISCONNECT报文的情况下关闭了网络连接
  • 服务端在没有收到DISCONNECT报文的情况下主动关闭了网络连接
  • 在MQTT 3.1.1中,如果满足任意一个情况,服务端会在连接断开后立刻发布遗嘱消息,5.0中可以通过设置属性延迟发布

保留消息

为什么需要保留消息

       如果不考虑持久会话的因素,那么MQTT订阅只有在客户端连接之后才能创建,所以服务端不能提前预知某个主题会被哪些服务端订阅或者某个客户端会订阅哪些主题,所以当消息到达服务端之后,服务端只会把消息分发给当前已经存在的订阅者,分发完成消息就会从服务端中删除,如果当前没有任何订阅者,消息就会立即丢弃,如果订阅端在在这之后上线的,就会错过这个消息,为了解决该场景的问题,MQTT提供了保留消息


如何使用保留消息

       我们可以在发送PUBLISH的时候把Retain设置为1或者True,表示当前消息是保留消息,保留消息进入服务端,会像普通消息一样转发给当前的订阅者,还会被保留在MQTT的服务端中,每当有新的订阅建立,MQTT服务端都会检索是否存在与这个订阅匹配的保留消息,然后把匹配的保留消息下发给订阅者,由于订阅的时候可以使用主题通配符,所以可能匹配到多个保留消息,这些消息将依次下发给订阅者

保留消息的更新

       通过保留消息,我们可以使订阅者上线后立即获得数据更新,不必等待新一次的消息,每个主题最多可以储存一条保留消息,如果主题下的保留消息已经存在,那么新到达的保留消息就会替换原来的保留消息,保留消息会一直储存在服务端中,由于他不属于会话状态的一部分,所以即便发布端会话过期,也不会影响保留消息存储,如果想要清空这个主题的保留消息,可以通过发送一个payload为空的保留消息来实现,这个为空的保留消息会合其他保留消息一样转发给订阅者,区别是在于不会被服务端存储,使用这种方式的话,我们需要确保订阅端不会把为空的消息视为一个错误


       需要注意的是,QoS 0 可能丢消息的特性,可能会导致保留消息删除不成功,QoS 1 可能重复到达的特性,保留消息又可能多次删除,如果不希望出现删除失败或者多次删除的情况,可以使用QoS 2 来发布 payload为空的保留消息

保留消息的过期时间

       如果担心一条保留消息失去了时效性,还长时间保留在服务端中导致被后来的订阅者消费的话,MQTT 5.0版本可以为保留消息设置过期时间,PUBLISH的 Message Expiry Interval 属性,单位是秒

保留消息的发送机制

       默认情况下,当保留消息当成普通消息向订阅者转发的时候,保留消息中的retain标识会被清除也就是设置为0,只有当新的订阅建立的时候,发送保留消息的retain会设置为1,表示这是一个保留消息


       针对上述情况多个服务端桥接的时候,会衍生一个问题,比如服务端A向服务端B订阅了主题,当服务端B收到一个保留消息向服务端A转发的时候清除retain标识,导致服务端A收到该保留消息后只会转发给订阅者,不会保存保留消息,在MQTT 5.0中,提供了 Retain As Published 的订阅选项,如果该选项设置为0,就是默认的逻辑,如果设置为1,那么保留消息当做普通消息转发的时候,Retain标识不会被清除,依然是1


       还有一个选项会影响保留消息的行为,在某些场景下,虽然客户端复用了上一次的会话,但是无法确定上一次会话中是否成功订阅了某个主题,所以只能再次订阅,如果订阅已经存在,其实服务端已经给客户端缓存了离线期间的消息,这种情况下,客户端在重连后,其实并不需要获取保留消息,但是现在只要有订阅建立,订阅匹配就会下发保留消息,为了解决这个问题,在MQTT 5.0中,提供了 Retain Handling的订阅选项文章来源地址https://www.toymoban.com/news/detail-437350.html

  • Retain Handling = 0,订阅建立的时候发送保留消息
  • Retain Handling = 1,订阅建立时若该订阅当前不存在则发送保留消息
  • Retain Handling = 2,订阅建立时不发送保留消息

保留消息的注意事项
  • 在MQTT中,同一条普通消息只能被同一个客户端消费一次,保留消息可能会被重复消费,客户端进行订阅,服务端下发匹配的保留消息,即时这个消息之前已经下发过了,只要保留消息在客户端的两次订阅期间没有更新,客户端就会重复消费到同一条消息,如果客户端的订阅是在保留消息到达服务端之前建立的,消息转发后 客户端重新连接,没有更新过保留消息,就是重复收到了两条同样的消息
  • 不能通过主动删除已经消费过的保留消息来避免重复,因为可能其他人也使用该主题下的保留消息,我们就不能去删除他,其次也没有办法正确判断当前服务器中的保留消息有没有被自己消费过,我们可以参考QoS 1 去重的做法,在保留消息的payload中增加一个时间戳,订阅者记录最后消费的消息的时间戳,和新到达的保留消息的时间戳进行比较,如果后者的时间戳更新,就是一个新的消息,反之就是一个重复的消息
  • 我们可以通过保留消息减少消息的发布频次,对于一些固定周期、状态等以确保新上线的客户端尽快取得数据,有了保留消息,我们可以只在状态发生变更时进行发布

到了这里,关于MQTT-保留消息和遗嘱消息的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 为什么需要数据仓库

    为什么不在OLTP环境下分析?  OLTP环境也会存储历史数据,但这些历史数据并不是业务运行所需的,这些历史数据需要经常归档到数据仓库,并且在OLTP数据库中删除。 相比之下,事务环境适用于连续处理事务,通常应用于订单录入以及财务和零售事务。它们并不依赖历史数据

    2024年01月25日
    浏览(49)
  • 为什么需要uboot?

    bootROM: 一种固化在芯片内部的只读存储器(ROM),用于启动和初始化系统。BootROM 中通常包含了一些预先编写好的代码,用于完成系统启动前的基本初始化和配置, 例如初始化时钟、GPIO控制器、中断控制器、存储设备(SD卡、NAND Flash、SPicy Flash)等硬件资源, 检测启动设备

    2023年04月23日
    浏览(45)
  • 为什么需要超时控制

    本文将介绍为什么需要超时控制,然后详细介绍Go语言中实现超时控制的方法。其中,我们将讨论 time 包和 context 包实现超时控制的具体方式,并说明两者的适用场景,以便在程序中以更合适的方式来实现超时控制,提高程序的稳定性和可靠性。 超时控制可以帮助我们避免程

    2024年02月03日
    浏览(41)
  • 为什么自动驾驶需要5G?

    什么叫自动驾驶? 自动驾驶分为6个等级: Level 0: 人工驾驶,无驾驶辅助系统,仅提醒。 Level 1: 辅助人工驾驶,可实现单一的车速或转向控制自动化,仍由人工驾驶(如定速巡航、ACC)。 Level 2: 部分自动驾驶,可实现车速和转向控制自动化,驾驶员必须始终保持监控(

    2024年02月08日
    浏览(50)
  • 爬虫时为什么需要代理?

    我们都知道爬虫时是需要代理地址介入的。使用代理可以隐藏你的真实IP地址,防止被网站封禁或限制访问。此外,代理还可以帮助你绕过地理限制,访问被封锁的网站或服务。但是请注意,使用代理也可能会带来一些风险,例如代理服务器可能会记录你的访问数据,或者代

    2024年02月06日
    浏览(44)
  • 爬虫为什么需要ip

    爬虫需要使用爬虫ip主要是为了解决以下问题: 1、反爬虫机制:许多网站会设置反爬虫机制来防止爬虫程序的访问,例如限制IP地址的访问频率、检测访问来源等。使用爬虫ip可以绕过这些限制,使得爬虫程序更难被检测到。 2、访问限制:有些网站可能会对某些地区的IP地址

    2024年02月02日
    浏览(41)
  • 为什么CPU需要时钟

    为什么CPU需要时钟这样一个概念? 什么是时钟脉冲,CPU为什么需要时钟,时钟信号是怎么产生的? 上面这个图的方波就是一个脉冲,类比于人类的脉搏跳动。一个脉冲称之为CPU的一个 时钟信号 ,或者 时钟脉冲 。一个脉冲周期就叫CPU时钟周期,一个时钟周期内时钟信号震荡一

    2023年04月11日
    浏览(38)
  • 为什么需要对相机标定?

    以下内容来自系统教程如何搞定单目/鱼眼/双目/阵列 相机标定? 点击领取相机标定资料和代码 为什么需要对相机标定? 我们所处的世界是三维的,而相机拍摄的照片却是二维的,丢失了其中距离/深度的信息。从数学上可以简单理解为,相机本身类似一个映射函数,其将输

    2024年02月06日
    浏览(40)
  • 什么是分库分表?为什么需要分表?什么时候分库分表

    不急于上手实战  ShardingSphere  框架,先来复习下分库分表的基础概念,技术名词大多晦涩难懂,不要死记硬背理解最重要,当你捅破那层窗户纸,发现其实它也就那么回事。 分库分表是在海量数据下,由于单库、表数据量过大,导致数据库性能持续下降的问题,演变出的技

    2023年04月26日
    浏览(132)
  • 为什么商业基础软件需要开源

    Bytebase 本身是一家商业软件公司,而作为最核心资产的代码从 Day 0 却是开源的。同时我们还是 star-history.com 的运营者,大家在各种开源渠道会看到它生成的图: 一直以来,常会被别人问起的一个问题,就是为什么 Bytebase 要开源。结合这 2 年多的实战经验,一次性把能想到的

    2024年02月13日
    浏览(75)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包