MQTT基础文档翻译(二):发布和订阅

原文链接

Publish & Subscribe - MQTT Essentials: Part 2

正文

欢迎来到MQTT要点系列的第二版,分为十章的关于MQTT协议核心特点和概念的系列文章。在系列文章的第一章,我们介绍了MQTT并讨论了MQTT协议的来源和历史。如果你错过了第一章,你绝对应该看一看。

我们有一个关于发布订阅模式的视频在文章末尾来帮助你补充相关知识

发布/订阅模式

发布订阅/模式提供了一种传统客户端-服务器架构的替代品。在客户端-服务器模型中,客户端直接与端点通信。而发布/订阅模型将消息发送者和接收者解耦,发布消息的客户端被称为发布者,接收消息的客户端被称为订阅者。发布者和订阅者永远不会直接通信。事实上,他们甚至不知道对方的存在。他们之间的通信被第三方组件(the broker)处理。broker的工作是过滤所有到来的消息,然后将消息分发给正确的订阅者。接下来,让我们深入了解一下发布订阅的相关特性。

发布订阅模式最重要的特性是消息发送者和接收者的解耦,这种解耦有几个方面

  • 空间解耦: 发布者和订阅者不需要知道对方(例如,不需要知道ip地址和端口)
  • 时间解耦: 发布者和订阅者不需要在同一时间运行
  • 同步解耦: 在两个组件上的操作在发布或接收消息时不需要被中断

总的来说,发布/订阅模式移除了消息发布者和接收者的直接交流。通过broker的过滤可以控制订阅者接收到哪些消息。它在三方面解耦:空间、时间、同步性

可扩展性

发布\订阅模式的可扩展性好于传统的客户端服务器架构。因为broker的操作有很高的并行性,而且消息可以以事件驱动的模式去处理。消息缓存和合理的路由选择通常是提高可扩展性的关键因素。尽管如此,拓展到百万级别的连接数仍然是一个挑战。这样高级别的连接数可以通过broker节点集群和负载均衡来解决(这个话题超过了这篇文章讲述的范围,我们在另外的文章中讲述相关的消息)

消息过滤

显而易见,broker在发布/订阅过程中扮演了重要的角色。那么,broker是如何管理所有的消息并在传输给某个订阅者消息时,只传递他感兴趣的话题下的消息呢?正如你所看到的,broker有一些过滤选项。

选项一: 基于主题的过滤

过滤的过程基于每条消息中的主题或话题。接收方客户端向broker订阅感兴趣的话题,从订阅之后开始,broker确保接收方客户端会收到所有被订阅主题下的消息。通常情况下,主题是一个有层次结构的字符串并借此结构可以实现基于有限数量表达式的过滤。

选项二: 基于内容的过滤

在基于内容的过滤中,broker基于内容中特殊的过滤语言来过滤消息。接收方客户端向broker订阅他感兴趣的查询条件。这个方法重大的缺点是消息内容必须提前知晓,而且不能被加密或有任何简单的变化。

选项三: 基于类型的过滤

在我们使用面向对象语言时,基于类型的过滤是一种常见的做法。例如,一个订阅者可以订阅所有”异常”类型的消息,或任何其他的子类型

当然,发布/订阅模式并非适应于所有的情况。在使用这种模式之前,你需要考虑一些事情。对发布者和订阅者的解耦是发布/订阅模式的关键,这为我们带来了一些挑战。比如说,你需要提前明白被发布的消息是如何组织的。针对基于主题的过滤,发布者和订阅者双发都需要知道要使用哪一个话题。另一个需要注意的事情是消息交付。发布者不能认为被发出的消息有被任何一方所监听,在某些时候,一条消息不属于任何订阅者的情况是存在的。

MQTT

现在我们来探索发布/订阅模式的一种实际应用——MQTT。正如你所想,MQTT体现了之前提到的发布/订阅模式所有特性:

  • MQTT在空间上解耦了发布者和订阅者,为了发布或订阅消息,发布者和订阅者只需要知道broker的主机名/IP地址和端口
  • MQTT实现了时间解耦。尽管MQTT通常会实时传递消息。但如果有需要,broker可以在客户端不在线时存储消息。(存储消息必须满足条件:客户端曾有一个持续会话,并且订阅话题时设置QoS级别大于0)
  • MQTT使用异步的方式工作。因为大多数客户端类库基于回调或类似的模型用异步的方式工作。任务在等待消息或者发布消息时不会阻塞。在特定的情况下,需要同步模式去等待一个特定的消息,一些开发库有同步的API,但是工作流通常时异步的。

MQTT另一个值得被提到的事是他在客户端一方非常易用。大多数发布/订阅模式系统相关的逻辑都在broker一方。当在运用MQTT客户端库时符合了发布/订阅模式的特性,并且让他成为一个适用于资源受限设备的轻量协议。

MQTT使用基于主题的消息过滤。每条消息带有一个主题,所以broker可以用主题信息来决定将这个消息发向哪个订阅者。在第五篇文章中,我们会了解更多关于主题的内容。如果需要,你也可以使用HiveMQ和我们的自定义扩展系统建立一个基于内容过滤的MQTT broker。

为了解决发布/订阅系统带来的挑战,MQTT有三个服务质量(Quality of Service)级别。你可以简单的认为消息成功的发布到broker,或成功的从broker发出。然而,存在一种情况:没有一个订阅者订阅某个特定的话题。如果这会带来一些问题,broker必须知道该如何处理这种情况。例如,HiveMQ MQTT broker有一个插件系统可以处理这种情况。你可以让broker采取一些行为,或者简单的将每条消息打印到数据中方便查阅。为了保持话题树结构的灵活性,必须认真的设计话题树并且为未来可能的变化留有足够的空间。如果你遵循这些策略,MQTT是一个完美的协议帮助你搭建产品。

与消息队列的区别

关于MQTT名称的由来和此协议是否有消息队列的实现有许多争议。我们将在这个主题上阐明一些观点,并说明MQTT和消息队列的区别。在我们上一篇文章中,我们提到MQTT中MQ是IBM的MQ系列产品,和消息队列无关。不管名字的来源具体是什么,有必要了解一些MQTT和传统消息队列的区别:

  • 消息队列存储着消息知道他们被消费。在你使用消息队列时,收到的每个消息都被存储在队列中,直到他们被客户端(通常被称为消费者)取走。如果没有消费者取走消息,那么消息会一直存储在队列中,直到被取走。在消息队列中,一条消息没有被任何客户端所处理就丢弃是不可能的。但是在MQTT中是可能的,例如没有客户端订阅某个话题时,发往该话题的消息将被丢弃。
  • 一条消息只被一个客户端处理。另一个巨大的区别是在传统的消息队列中,一条消息只能被一个消费者处理。所有消费者等待一个队列。 在MQTT中,行为是完全相反的,每一个订阅某个主题的订阅者都会获得消息。
  • 队列需要被命名而且需要被明确的创建。一个队列比话题更加死板。在一个队列可以使用之前,队列必须被另外的命令明确的创建,只有在被明确创建并命名后才可以用于生产和消费消息。相反,MQTT 话题更加灵活,可以被任意的创建。

如果您可以想到任何其他的不同被我们忽略了,希望可以在评论中指出。

系列文章的第二篇结束了。下一周我们去仔细了解以下什么是MQTT客户端和broker还有他们是如何连接的。

MQTT
MQTT基础文档翻译(三):MQTT客户端和Broker和MQTT服务器和连接建立的解释
MQTT基础文档翻译(一):MQTT协议介绍
© 2020 Liujianfeng
Powered by hexo | Theme is white