Ada*_*nek 8 messaging protocols mqtt iot
假设我有一个IoT设备,我即将控制(让我们说开/关)和监控(例如收集温度读数).似乎MQTT可能是合适的.我可以将消息发布到设备以控制它,并且设备可以向代理发布消息以报告温度读数.到现在为止还挺好.
当我尝试设计API来控制设备时,问题就开始出现了.
让设备订阅两天主题:
然后我按照某种顺序向这些主题发布消息.但鉴于消息传递通常是异步过程,因此无法保证设备接收的消息顺序.
因此,如果按以下顺序发布两条消息:
它们可以按相反的顺序接收,使设备开启,这可能会产生严重的后果,具体取决于具体情况.
当然,API可以以其他方式设计,例如,可能只有一个主题
并且各个消息的有效载荷将带有单个消息的含义(开/关).因此,如果消息按给定顺序发布到此主题,则应在设备上以完全相同的顺序接收消息.
但是,如果不能保证发布到个别主题的顺序怎么办?假设物联网设备的以下系统架构:
/ control service \
application -> broker -> control service -> broker -> IoT device
\ control service /
Run Code Online (Sandbox Code Playgroud)
该系统的组件是:
重要的是,在大多数现代分布式系统中,控制服务是一个分布式的多实例实体,能够一次处理来自应用程序的多个控制消息.因此,应用程序发布的消息顺序在传送到IoT设备时最终会完全混合.
现在考虑到大多数MQTT代理只实现QoS0和QoS1但没有QoS2它会变得更加有趣,因为这样的控制消息可能会被多次传递(假设QoS1 - 请参阅/sf/answers/2167134091/) .
我的观点是控制消息的单独主题是一个坏主意.单个主题也是如此.在这两种情况下都没有消息传递顺序保证.
我想到的这个特定问题的唯一解决方案是消息版本控制,以便在具有更新版本属性的另一个消息之后传递时可以简单地跳过旧的(过时的)消息.
我错过了什么吗?
明确地.您提出的示例是一个通用控制系统,附加到一些面向消息的方案.在引用基于消息的体系结构时,可以使用许多模式. Microsoft的这篇文章将消息模式分为两个主要类:
命令行为的最通用的模式是发出命令,然后测量系统的状态,以验证该命令进行.如果您忘记验证,您的系统有一个开环.这种开放循环(不幸的是)在IT系统中很常见(因为它很容易被遗忘),并且经常导致错误和其他不良行为,例如上面描述的那些.因此,处理命令的正确方法是:
另一方面,事件被简单地解雇了.作为一个活动的发布者,我不应该担心谁收到活动,以什么顺序等等.现在,还应该指出任何体面的消息经纪人(例如RabbitMQ)的使用通常都有很强的保证.消息将按照最初发布的顺序发送. 请注意,这并不意味着它们将按顺序处理.
因此,如果您将命令视为事件,则系统保证您的系统迟早会起作用.
消息版本控制是解决此问题的唯一方法吗?
消息版本控制通常是指消息类本身的属性,而不是类的特定实例.它通常在存在基于消息的API的多个版本时使用,并且必须向后兼容.
您所指的是唯一的消息标识符.Guids特别方便确保每条消息都有自己唯一的ID.但是,我认为基于消息的体系结构中的重复数据删除是一种反模式.使用消息传递的一个后果是重复是可能的,因此您应该尝试将系统行为设计为无状态和幂等.如果无法做到这一点,则应该认为消息传递可能不是满足需要的正确通信解决方案.
使用命令事件二分法作为示例,您可以执行以下事务:
如果控制器在某些超时后没有收到通知,则控制器可以重试该命令.请注意,"light on"是一个幂等命令,因为对它的多次调用将具有相同的效果.
当状态更改时,立即发送新状态,然后每隔 x 秒定期发送一次。使用此解决方案,您的系统在一段时间后会进入所需的状态,即使它暂时与网络断开连接(电池电量低)。
顺便说一句:你没有错过任何东西。