avatar

目录
物联网通讯之MQTT协议基础篇(二)发布和订阅

MQTT系列导航

上一篇: 物联网通讯之MQTT协议基础篇(一)MQTT介绍

下一篇: 物联网通讯之MQTT协议基础篇(三)客户端/代理者、MQTT服务器、建立连接

发布/订阅模式

发布/订阅模式(pub/sub)提供了传统客户端/服务器架构的替代方案。

客户端/服务器模型中,客户端直接与端点通信。

发布/订阅模型 将发送消息的客户端(发布者/publisher)与接收消息的客户端(订阅者/subscribers)分离。

发布者和订阅者不直接相互联系。

它们之间的连接由第三个组件(代理者/broker)处理。

代理的工作是过滤所有传入的消息并将它们正确地分发给订阅者。

MQTT Publish/Subscribe MQTT Publish / Subscribe Architecture

发布/订阅模型最重要的方面是消息的发布者与订阅者的解耦(decoupling)。

这种解耦有几个维度:

  • 空间解耦:发布者和订阅者不需要相互了解(例如,无需交换 IP 地址和端口)
  • 时间解耦:发布者和订阅者不需要同时运行
  • 同步解耦:两个组件的操作在发布或接收时不需要中断

note: 解耦包括三个维度:空间(space)、时间(time)和同步(synchronization)。

总之,发布/订阅模型消除了消息发布者和接收者/订阅者之间的直接通信。

此外,代理的过滤(filtering)活动可以控制哪个客户端/订阅者接收哪个消息。

可拓展性 Scalability

发布/订阅模式的扩展性比传统的客户端/服务器模式更好。这是因为代理上的操作可以高度并行化,并且可以通过事件驱动(event-driven)的方式来处理消息。

消息缓存和消息智能路由通常是提高可扩展性的决定性因素。

尽管如此,扩展到数百万个连接仍具有挑战性。

可以通过集群代理节点实现如此高水平的连接,使用负载平衡器将负载分配到更多的单个服务器上。

消息过滤 Message filtering

显然,代理者发布/订阅 过程中起着重要的作用。

那么,代理如何过滤所有消息,使得每个订阅者只接收感兴趣的消息呢?

代理者有几个过滤选项:

Option 1: 基于主题的过滤 Subject-based filtering

这种过滤基于每条消息的主题(subject)或话题(topic)。

订阅者(客户端)向代理者订阅感兴趣的主题。代理者要确保 订阅者 获取到所有已发布主题的消息。

通常,主题是具有分层结构的字符串,允许基于有限数量的表达式进行过滤。

Option 2: 基于内容的过滤 Content-based filtering

基于内容的过滤中,代理者根据特定的内容来过滤消息,这种特定的内容称作过滤语言( filter-language)。订阅者(客户端)根据需要来查询过滤后的消息。这种方法的一个显着缺点是必须事先知道消息的内容,内容不能被加密或轻易更改。

Option 3: 基于类型的过滤 Type-based filtering

当使用面向对象的语言时,基于消息或事件的类型(type)或是(class)进行过滤是一种常见做法。例如,订阅者可以监听所有类型为 Exception任何其他子类 的消息。

显然,发布/订阅模型并不适用于每个用例。因此在使用此模型之前,还需要考虑一些注意事项。发布者和订阅者的解耦是发布/订阅模型的关键,它本身也存在一些挑战。例如,你得事先了解已发布数据的结构。对于基于主题的过滤,发布者和订阅者都需要知道要使用哪些主题。另一件事需要关注的是消息传递。发布者不能假设正好有人正在监听它发送的消息。在某些情况下,可能压根儿就没有订阅者读取到特定的消息。

MQTT

现在我们已经大致探讨了发布/订阅模型,接下来让我们专门关注 MQTT。根据我们想要实现的目标,MQTT 体现了上述提到的发布/订阅模型的所有方面:

  • MQTT 在空间上分离了发布者和订阅者。要发布或接收消息,发布者和订阅者只需要知道代理的主机名/IP和端口。

  • MQTT 按时间解耦。尽管大多数 MQTT 用例都近乎实时地传递消息,但如果需要,代理可以为不在线的客户端存储消息。

    必须满足以下两个条件才能存储消息:一是客户端已连接到持久会话,二是客户端订阅了服务质量QoS大于 0 的主题。

  • MQTT 异步工作。由于大多数客户端库异步工作,并且基于回调或类似的模型,因此任务在等待消息或发布消息时不会阻塞。

    在某些用例中,同步是可取的,也是可能的,为了等待某个消息,一些库具有同步 API,但流程通常是异步的。

还有一件事儿,MQTT在客户端特别易于使用。虽然大多数发布/订阅系统都有代理端的逻辑,但在使用客户端库时,MQTT 才是发布/订阅模型的本质,这使其成为适用于小型受限设备轻量级协议。

MQTT 使用基于主题的消息过滤。每条消息都包含一个主题subject/topic),代理者可以使用主题来确认订阅客户端是否收到消息。有关主题概念的更多信息将在物联网通讯之MQTT协议基础篇(五)进行讨论。

为了应对发布/订阅系统的挑战,MQTT 具有三个服务质量 (QoS) 级别。因此我们可以轻松让消息成功地从客户端传送到代理者(或从代理者传送到客户端)。然鹅,有可能并没有人订阅特定的主题。如果存在这种问题,代理者必须知道如何处理这种情况。

例如,HiveMQ MQTT 代理有一个插件系统可以解决这种情况。你可以让代理者采取行动或简单地将每条消息记录到数据库中以进行历史分析。

MQTT与消息队列的区别

关于 MQTT 的名称以及该协议是否作为消息队列(message queue)来实现,存在很多混淆。在上一篇文章中,我们知道 MQTT 是指 IBM 的 MQ系列产品,与“消息队列”无关。不管这个名字来自哪里,理解 MQTT 和传统消息队列之间的区别是很有用的:

  • 消息队列存储消息直到消息被消费/使用
    使用消息队列时,每条传入的消息都存储在队列中,直到被客户端(通常称为消费者)接收为止。如果没有客户端接收到消息,消息将保持在队列中并等待被消费。在消息队列中,消息不可能不被任何客户端处理,而在 MQTT 中,可能并没有人订阅主题。

  • 消息队列中一条消息只被一个客户端消费
    另一个很大的区别是,在传统的消息队列中,一条消息只能由一个消费者处理。 负载分布在队列的所有消费者之间。在 MQTT 中,行为完全相反,订阅主题的每个订阅者都会收到消息。

  • 消息队列中队列需命名且必须显式创建
    队列比主题严格得多。在使用队列之前,必须使用单独的命令来显式创建队列。 只有在队列命名和创建之后,才可以发布或消费消息。相比之下,MQTT 主题非常灵活,可以即时创建。

参考

文章作者: TaQini
文章链接: http://taqini.space/2021/09/10/mqtt-publish-subscribe/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 TaQini
打赏
  • Wechat
    Wechat
  • Alipay
    Alipay

评论