推送 & 订阅 - MQTT 核心系列: 第二章

推送 & 订阅 - MQTT 核心系列: 第二章

作者:HiveMQ 团队

翻译:索隆有几把刀

欢迎来到《MQTT 核心系列》的第二章,这个系列一共有十章,用来介绍MQTT的核心特性和概念。在这个系列的第一章中,我们介绍了MQTT,谈论了它的历史和由来。假如您还没有阅读第一章,您最好去读一读。

发布订阅模式

发布订阅模式为传统的客户/服务器(后面以c/s代替)模型提供了一种替代方案。在c/s模型中,客户端会直接与终端交互。但是发布订阅模式能让发送消息的客户端与接受消息的客户端解耦。消息发布者和消息订阅者不再直接进行交互。事实上,他们甚至不关心对方是否存在。它们之间的额关系通过第三方管理,也就是broker。broker负责过滤所有进入的消息,并将它们正确的分发给订阅者。那么,让我们更深入的了解一下关于发布/订阅的一些概念(我们将稍后再讨论MQTT的细节)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RarrTWYI-1614179330262)(https://www.hivemq.com/img/svg/mqtt-publish-subscribe.svg)]

对于发布订阅模式最重要的概念就是对消息发布者和发布订阅者的解耦。这个解耦体现在如下几个方面:

  1. 空间解耦: 消息发布者和消息订阅者不需要知道彼此。(例如,不需要交换ip地址和端口)
  2. 时间解耦: 消息发布者和消息订阅者不需要同时工作。
  3. 同步解耦: 在接受或发送消息期间,通讯双方可以不用停下它本来的工作

总的来说,发布订阅模式解除了消息发布者和消息接受者之间的直接通信。broker的过滤动作让消息准确的投送到订阅者哪里成为可能。解耦体现在三个方面,分别是空间,时间,和同步。

可伸缩性

相较于传统的c/s模式,发布订阅模式还具有更好的伸缩性。这是因为broker采用事件驱动的方式处理消息,且能应对高并发请求。消息缓存和消息的智能路由通常会被视为提高伸缩性的关键因素,但是面对数以百计的连接,要保证良好的伸缩性依然是一个不小的挑战。想要满足如此高的连接,我们可以通过部署broker集群,然后通过负载均衡把压力分散到各个节点上(这超出了我们这篇文章的的讨论范围,我们将在另外的文章中讨论这个问题)。

消息过滤

显然,broker在订阅发布模式中扮演至关重要的角色。哪么broker是如何过滤所有消息以实现让订阅者只接受它们感兴趣的消息的呢?如你说见,broker拥有如下几种过滤选项:

### 选项 1: 主题过滤

这种过滤基于消息的主题。消息接受方会向broker订阅感兴趣的主题。从此以后,broker会保证所有该主题的消息会被推送给消息接收方。通常来说,主题是由具有层级关系的字符串组成,这样有助于模糊过滤。

### 选项 2: 内容过滤
在基于内容的过滤中,broker基于特定的内容过滤消息。消息过滤方会订阅它们感兴趣的内容。但是这种过滤方式有一个显著的缺点,那就是这个消息的内容必须被事先知道,并且消息不能被加密或者轻易修改。

### 选项 3: 类型过滤
当使用面向对象的语言时,基于消息的类型/类进行过滤是一种常规的做法。例如,一个消息订阅者能接受所有Exception类型以及其子类的消息。

当然,并不是任何场景都适用订阅发布模式。在使用它之前,有几个问题值得你考虑。对消息发布者和消息订阅者的解耦是发布订阅模式的关键,但这也带来了一些挑战。例如,你需要事先了解被投递的消息的数据结构。对于主题过滤,双方需要事先协商好主题。另外需要格外注意的就是消息投递,消息发送方不能假定一定有人在监听消息,因为可能并没有人订阅这个消息。

## MQTT

我们已经大致讨论了的订阅发布模式,现在让我们继续研究MQTT。还记得我们前面提到的解耦体现在三个方面吗?MQTT做到了

* MQTT 在空间上让消息发布方和消息订阅方解耦。为了推送或者接受消息,消息发布者和消息订阅者只需要知道broker的ip和端口号。
 * MQTT对时间上的解耦。虽然大部分人使用MQTT来进行几乎实时的消息投递,但是如果有需要,broker能为不在线的客户端把消息存储起来。(想要存储消息必须满足两个条件,第一,客户端必须已经创建了持久化会话,第二,主题订阅的服务质量参数必须大于0)
 * MQTT支持异步运行。大部分客户端会基于回调或类似的方式来实现异步操作,这样任务就不会因为发送消息或者接受消息而阻塞。当然有些特殊场景需要进行同步操作,MQTT也提供了API.但是通常都是异步的。

另外值得一提的是,在客户端使用MQTT非常简单。和大部分订阅发布系统一样,MQTT在broker侧需要进行一些逻辑处理,但是当我们在用MQTT开发客户端时,就会知道它是真的香。这也让它成为一种适用于小型和受限设备的轻量级协议。

当MQTT使用主题过滤策略时,broker会根据每条消息对应的主题来决定消息应该投送给谁。这个系列的第五章会详细讲解主题相关的内容。如果有需要,我们可以使用HiveMQ MQTT broker和自定义拓展系统来设置内容过滤策略。

为了应对订阅发布系统的挑战,MQTT设计了三个级别的服务质量(QoS)。你能简单的指定一个消息从消息发送方投递给broker,或从broker推送到消息接受方。然而,可能出现这样一种情况,那就是并没有客户端订阅某个特定的主题。假如这成为一个问题,那么broker必须直到如何去解决它。例如, HiveMQ MQTT broker 有一个插件系统能解决这种问题。你可以让broker采取措施或者简单的将消息记录到数据库中以备做历史分析。为了保证层级主题树的伸缩性,我们有必要精心设计一下主题树,还要考虑为将来可能的主题预留空间。如果你能遵循这些策略,MQTT将会很好帮助你的生产。

与消息队列的区别

MQTT这个名称容易让人感到迷惑,它到底是不是一个消息队列。现在我们将尝试去理清它们间的区别。在前面一章中,我们已经说过MQTT是IBM的MQseries产品,它与消息队列无关。不论这个名字怎么来的,搞清楚MQTT与传统的消息队列之间的区别都非常重要:

1. 当你使用消息队列的时候,消息队列会存储消息直到该消息被消费掉。每一个入站的消息都会被保存起来,直到他被一个客户端(通常被成为消费者)捡出。如果没有任何客户端去捡出这条消息,这条消息将被保存在队列里面。

2. 一个消息智能被一个客户端消费。另一个巨大的差异是在传统的消息队列中,一个消息只能被一个消费者消费。负载会被分配到这个队列的所有消费者上。在MQTT中情况恰好相反,每一个订阅了该主题订阅者都会收到该主题的消息。

3. 队列必须命名和明确创建。队列远比主题严格。在使用一个队列前,必须使用单独的命令显式创建它。只有这个队列被显式的创建并命名了,这个队列才能被用来推送和消费消息。相比之下,MQTT的主题显得非常灵活,我们能在发送消息的过程中创建它。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值