欢迎来到 MQTT 入门的第二部分。关于 MQTT 协议中的核心特性和概念的博客系列。在第二篇文章中,我们将讨论发布 /订阅模式。首先我们来看一下 Publish / Subscribe 本身的一般特性,然后我们将重点关注 MQTT。我们还将解释 MQTT 如何与传统的消息队列协议不同。 在第一篇文章中,我们介绍了 MQTT ( www.iotn2n.com ),解释了它的起源和历史 。如果你还没有阅读它,你应该肯定看看。
发布 /订阅模式 发布 /订阅模式( pub / sub )是传统客户端 - 服务器模型的替代方案,其中客户端直接与端点通信。但是,Pub / Sub 解耦了客户端,客户端正在从另一个客户端(或多个客户端)发送特定消息(称为发布者),该客户端正在接收消息(称为订阅者)。这意味着发布者和订阅者不知道彼此的存在。有一个称为代理的第三个组件,发布者和订阅者都知道它,它过滤所有传入的消息并相应地分发它们。所以,让我们深入一点关于刚刚提到的这方面的细节。记住这仍然是 pub / sub 的基本部分,按惯例,我们将在稍后讨论 MQTT 的细节。
MQTT 发布 /订阅 如已经提到的, pub / sub 中的解耦的主要方面是发布者和接收者的去耦合,其可以在更多维度上区分:
总之,发布 /订阅消除消息的发布者和接收者的耦合,通过消息的过滤,可能仅某些客户端接收某些消息。解耦具有三个维度:空间,时间,同步。
可扩展性 与传统的客户端 - 服务器方法相比, Pub / Sub 还提供了更大的可扩展性。这是因为消息代理上的操作可以高度并行化和事件驱动处理。通常,消息缓存和消息的智能路由对于提高可伸缩性也是决定性的。但是,扩展发布 /订阅到数百万的连接肯定是一个挑战。这可以使用集群代理节点来实现,以便将负载分布到具有负载平衡器的更多个别服务器上。(我们将在一个单独的文章中详细讨论,这将超出本章讨论范围)。
消息过滤 让人感兴趣的是,代理如何过滤所有消息,如何让每个订阅者只获取它感兴趣的消息? 选项 1 :基于主题的过滤 过滤基于作为每个消息的一部分的主题或主题。接收客户端订阅它对代理感兴趣的主题,并从那里基于订阅的主题获得所有消息。主题通常是具有层次结构的字符串,允许基于有限数量的表达式进行过滤。 选项 2 :基于内容的过滤 基于内容的过滤名如其文,当代理过滤基于特定内容过滤器语言的消息。因此,客户端订阅对他们感兴趣的消息的过滤器查询。这是一个很大的缺点是,消息的内容必须事先知道,并且不能被容易地加密或改变。 选项 3 :基于类型的过滤 当使用面向对象的语言时,通常基于消息(事件)的类型 /类进行过滤。在这种情况下,订阅者可以侦听来自类型异常或其任何子类型的所有消息。 当然发布 /订阅不是万能的,在使用它之前,有一些事情要考虑。发布者和订阅者的解耦是 pub / sub 中的关键,它带来了一些挑战。您必须事先知道已发布数据的结构。在基于主题的过滤的情况下,发布者和订阅者需要知道要使用的正确主题。另一方面是消息的递送,并且发布者不能假定某人正在收听他发送的消息。因此,可以是任何订户都不读取消息的情况。
MQTT 现在我们已经学习了很多关于发布 /订阅的基础知识,可以了解关于 MQTT 的细节。MQTT 体现了所有提到的方面,取决于你想要实现它。 MQTT 解耦发布者和订阅者的空间。所以他们只需要知道代理的主机名 / IP 和端口,以便发布 /订阅消息。它也与时间解耦,但是这通常只是一种降低标准的行为,因为用例主要是近实时地传递消息。当然,代理能够为不在线的客户端存储消息。(这需要两个条件:客户端已连接一次,其会话是持久的,并且已订阅了服务质量 ( http://www.hivemq.com/mqtt-essentials-part-6-mqtt-quality-of-service-levels/)大于 0 的主题)。 MQTT 还能够解耦同步,因为大多数客户端库都是异步工作的,并且基于回调或类似模型。因此,它不会在等待消息或发布消息时阻止其他任务。但是存在某些使用情况,其中同步是期望的并且也是可能的。因此,一些库具有同步 API ,以便等待某个消息。但通常流是异步的。另一件应该提到的是 MQTT 在客户端特别容易使用。大多数 pub / sub 系统在代理端处理绝大多数业务逻辑,但是当使用客户端库时, MQTT 实际上是 pub / sub 的本质,并且使其成为用于小型和受限设备的轻量级协议。 MQTT 使用基于主题的消息过滤。因此,每个消息包含一个主题,代理使用它判读订阅客户端是否将接收消息。有关主题的 更多详细信息,请参阅 MQTT 入门的第 5 部分 ( http://www.hivemq.com/mqtt-essentials-part-5-mqtt-topics-best-practices/)。还可以使用 EMQ MQTT 代理和其定制插件系统 ( http://www.hivemq.com/docs/plugins/latest/)进行基于内容的过滤。 为了处理通常的发布 /订阅系统的挑战,MQTT 具有服务质量( QoS )水平。可以很容易地指定消息从客户端成功传递到代理或从代理到客户端。但仍然有可能没有人订阅特定主题。如果这是这种情况,它取决于代理如何处理这种情况。例如, EMQ MQTT 代理具有一个插件系统 ( http://www.hivemq.com/blog/www.hivemq.com/docs/plugins/latest/),它能够识别这种情况并采取行动或仅将每条消息记录到数据库中以用于历史分析。为了减轻主题的不灵活性,重要的是非常仔细地设计主题树,并为将来的用例留出扩展空间。如果你遵循这些策略, MQTT 是完美的生产设置。
区分消息队列 有许多关于 MQTT 的混淆,它的名称以及是否被实现为消息队列。我们将试图把澄清这个问题,并解释分歧。在我们的最后一篇文章中, 我们已经指出 MQTT 名称来自一个名为 MQseries 的 IBM 产品,与“消息队列”没有任何关系。但是不管名称如何, MQTT 和传统消息队列之间的区别是什么? 消息队列存储消息,直到消费 队列使用消息队列时,每个传入消息将存储在该队列中,直到任何客户端(通常称为消费者)接收消息。否则,消息将只停留在队列中,并等待消费。不可能出现没有客户端端处理的消息的消息场景,但在在 MQTT 中,有可能出现没有订阅主题的场景。 消息将只由一个客户端消费 另一个很大的区别是,在传统队列中,消息只由一个消费者处理。使得负载可以分布在特定队列的所有用户之间。在 MQTT 中,恰恰相反,每个订阅者只要订阅主题就能获得消息。 队列是必须事先定义,必须显式创建 队列远比主题更不灵活。在使用队列之前,必须事先定义并显式创建它。只有在此之后,才有可能发布或使用消息。在 MQTT 主题非常灵活,可以即时创建。 如果我们错过了任何其他的差异,我们会喜欢你的意见在评论中。 欢迎查看 MQTT 详情( www.iotn2n.com )