gpt4 book ai didi

protocols - 如何通过基于云的系统强制通过 MQTT 传递到 IoT 设备的消息顺序(API 设计问题)

转载 作者:行者123 更新时间:2023-12-04 07:51:49 26 4
gpt4 key购买 nike

假设我有一个物联网设备,我将要控制(可以说打开/关闭)和监控(例如收集温度读数)。看起来 MQTT 可能是合适的。我可以向设备发布消息以控制它,设备可以向代理发布消息以报告温度读数。到现在为止还挺好。

当我尝试设计 API 来控制设备时,问题开始出现。

让设备订阅两个主题:

  • /device-id/control/on
  • /device-id/control/off

  • 然后我按某种顺序向这些主题发布消息。但鉴于消息传递通常是一个异步过程,因此无法保证设备接收消息的顺序。

    因此,如果按以下顺序发布两条消息:
  • /device-id/control/on
  • /device-id/control/off

  • 它们可以以相反的顺序接收,而让设备打开,这可能会产生严重的后果,具体取决于上下文。

    当然,API 可以以其他方式设计,例如可能只有一个主题
  • /device-id/control

  • 并且单个消息的有效载荷将携带单个消息的含义(开/关)。因此,如果消息以给定的顺序发布到此主题,则预计它们将在设备上以完全相同的顺序接收。

    但是如果不能保证发布到单个主题的顺序怎么办?假设物联网设备的系统架构如下:
                           / control service \
    application -> broker -> control service -> broker -> IoT device
    \ control service /

    该系统的组成部分是:
  • 通过向代理发布消息来有效控制设备的应用程序
  • 一个典型的消息代理
  • 带有一些业务逻辑的控制服务

  • 重要的部分是,在大多数现代分布式系统中,控制服务是一个分布式、多实例实体,能够一次处理来自应用程序的多个控制消息。因此,应用程序发布的消息顺序在传递到 IoT 设备时可能会完全混合。

    现在考虑到大多数 MQTT 代理仅实现 QoS0 和 QoS1 而没有实现 QoS2,它变得更加有趣,因为这样的控制消息可能会被多次传递(假设 QoS1 - 参见 https://stackoverflow.com/a/30959058/1776942)。

    我的观点是控制消息的单独主题是一个坏主意。单个主题也是如此。在这两种情况下,都没有消息传递顺序保证。

    我想到的这个特定问题的唯一解决方案是消息版本控制,以便在具有更新版本属性的另一条消息之后传递时可以简单地跳过旧的(过时的)消息。
  • 我错过了什么吗?
  • 消息版本控制是解决此问题的唯一方法吗?
  • 最佳答案

    我错过了什么吗?

    明确地。您提出的示例是一个通用控制系统,附加到一些面向消息的方案。在提及基于消息的体系结构时,可以使用多种模式。 This article Microsoft 将消息模式分为两大类:

  • 命令
  • 事件

  • 命令行为的最通用模式是发出命令,然后测量系统状态以验证命令是否已执行。如果您忘记验证,则您的系统有一个开环。这种开环(不幸的是)在 IT 系统中很常见(因为很容易忘记),并且通常会导致错误和其他不良行为,例如上述行为。因此,处理命令的正确方法是:
  • 发出命令
  • 查询系统状态
  • 评估下一步行动

  • 另一方面,事件只是被触发。作为一个事件的发布者,担心谁接收事件,以什么顺序等等,不是我的事。强有力的保证消息将按照它们最初发布的顺序进行传递。 RabbitMQ

    因此,如果您将命令视为事件,那么您的系统迟早会起作用。

    消息版本控制是解决此问题的唯一方法吗?

    消息版本控制通常是指消息类本身的属性,而不是该类的特定实例。当存在多个版本的基于消息的 API 并且必须相互向后兼容时,通常会使用它。

    您所指的是唯一的消息标识符。 Guids对于确保每条消息都有自己的唯一 ID 尤其方便。但是,我认为基于消息的架构中的重复数据删除是一种反模式。使用消息传递的后果之一是可能出现重复,因此您应该尝试将系统行为设计为无状态和 Note that this does not mean they will be processed in order. .如果这是不可能的,则应考虑消息传递可能不是满足需求的正确通信解决方案。

    以命令-事件二分法为例,您可以执行以下事务:
  • Controller 发出命令,为命令分配一个唯一的标识符。
  • 控制系统接收命令并开启。
  • 控制系统发布“开灯”事件通知,其中包含用于打开灯的命令的唯一 ID。
  • Controller 接收通知并将其与原始命令相关联。

  • 如果 Controller 在一段时间后没有收到通知, Controller 可以重试该命令。请注意,“点亮”是一个幂等命令,因为多次调用它会产生相同的效果。

    关于protocols - 如何通过基于云的系统强制通过 MQTT 传递到 IoT 设备的消息顺序(API 设计问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35096109/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com