阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MQTT基础——Part 2. 发布/订阅模式

114次阅读
没有评论

共计 2927 个字符,预计需要花费 8 分钟才能阅读完成。

本节主要讲述发布 / 订阅模式。首先关注发布 / 订阅的基本特征,然后再聚焦到 MQTT 本身,着重讲述 MQTT 协议与传统消息队列协议的不同。

MQTT 基础——Part 1. 认识 MQTT http://www.linuxidc.com/Linux/2016-10/136408.htm

一、发布 / 订阅模式

发布 / 订阅模式即 Pub/Sub,是传统客户端 / 服务器模型(客户端直接连接服务器)的替代。传统的客户端 / 服务器模型是客户端直接连接到服务端(Endpoint),而发布 / 订阅模式实现了客户端的解耦。客户端(Publisher,消息发布者)发送特定的消息到另一个客户端(Subscriber,消息接收者)。这意味着发布者和订阅者都无需关心对方的存在与否。它们之间还有第三个组件,即消息经纪人(Broker),所有的发布者和接收者都要连接到消息经纪人,消息经纪人会过滤所有到来的消息,并根据需要分发这些消息。

发布 / 订阅模式实现了发布者和订阅者之间的解耦,可以从多维度进行区分:
1)空间解耦:发布者和订阅者均无需知道彼此的存在(比如对方的 IP 地址和端口)
2)时间解耦:发布者和订阅者无需同时运行
3)同步解耦:在发布或接收期间,双方组件的操作不会暂停
总的来说,发布 / 订阅模式从消息上对发布者和订阅者进行了解耦,并且通过对消息的过滤实现了只有某些客户端才能受到相应的消息。解耦包含了三个维度:空间、时间、同步。

可扩展性

发布 / 订阅模式还提供了比传统的客户端 - 服务器模式更好的可扩展性。这是因为,在经纪人 Broker 上的操作,是可以高度并行和基于事件驱动进行处理的。而且还可以对消息进行缓存和对消息进行智能路由,以进一步改善可扩展性。但是,要把发布 / 订阅模式扩展到支持数百万的连接,在技术上仍然是一个挑战。这一点可以通过对经纪人 Broker 节点进行集群来实现,以便通过负载平衡器把负载分配到更多的服务器节点来实现。

消息过滤

经纪人 Broker 怎样过滤所有的消息,以及怎样让每个订阅者只获得他感兴趣的消息。

选项 1:基于主题的过滤

过滤是根据标题(Subject)或主题(Topic)的,而标题或主题是每一个消息的组成部分之一。正在接收的客户端订阅了它感兴趣的主题 Topic,就可以从经纪人 Broker 那里得到它基于订阅主题 Topic 的所有消息。主题 Topic 通常是一个具有分层结构的字符串,可以基于有限数量的表达式进行过滤。

选项 2:基于内容的过滤

基于内容的过滤正如名字的暗示,是指经纪人 Broker 过滤基于特定内容、特定过滤器语言的消息。因此客户端订阅他们感兴趣的消息的过滤查询。这种过滤方法有一个较大的缺点,即消息的内容必须事先已知,并且消息不容易进行加密或修改。

选项 3:基于类型的过滤

在使用面向对象的编程语言时,有一种常见的做法,基于消息或事件的类型 / 类别进行过滤。在这种情况下,订阅者可以监听所有的消息,并从类型异常或子类型中获取消息。
当然,发布 / 订阅模式并不能解决一切,在使用此模式之前需要考虑一些事情。发布者和订阅者之间的解耦是发布 / 订阅模式的关键,这给使用它带来了一些挑战。你必须事先知道发布的数据的结构。在基于主题的过滤的场景,无论是发布者还是订阅者,都需要理解怎样正确的使用主题。另一方面是消息的交付,发布者不能想当然地认为有人会监听他发送的消息。因为在一些情况下,发布的消息可能没有任何一位订阅者。

MQTT

现在我们对发布 / 订阅模式已经有了一定的了解,但对于 MQTT 还不够。MQTT 体现了前面所有提及的方面,这取决于你想达到什么目标。MQTT 从空间上对发布者和订阅者进行了解耦。因此,客户端只需知道 Broker 的主机名(或 IP)和端口,以实现发布 / 订阅消息。MQTT 还从时间上对发布者和订阅者进行了解耦,但这往往是倒退的行为,因为大多数使用场景都是以近实时的方式传递消息。当然,Broker 还要能够存储信息,方便那些不在线的客户端(订阅者)。(这需要满足两个条件:客户端已连接一次,它的会话是持久的;并且客户端订阅了服务质量 QoS 大于 0 的主题,关于 QoS 在后续会讲到)。
MQTT 还能够解耦同步,因为大多数客户端库是异步工作的,是基于回调或类似模型的实现。所以客户端在等待消息或发布消息时不会阻止其它任务的执行。但也有一些场景需要使用同步,而且这也是可以实现的。因此有些客户端库提供了同步 API,以等待某种消息。但通常的流程都是异步的。还应该特别强调一点,MQTT 在客户端特别容易使用。大多数的发布 / 订阅系统的实现逻辑通常都在 Broker 端,而且 MQTT 协议仅仅使用了发布 / 订阅模式的基础内容,这使得 MQTT 确实是轻量级协议,确实是为小型和受限的设备而设计的协议。

MQTT 使用了基于主题的过滤方式。因此,每一个消息都包含了一个主题 Topic,要判断订阅了主题的客户端是否能够接收消息,Broker 会使用主题 Topic 进行查找。后续会详细讨论主题 Topic,以及接收消息的各种可能性。也会介绍 MQTT Broker 的实现之一——HiveMQ 的基于内容的过滤以及它自定义的插件系统。
通常为了解决发布 / 订阅系统的挑战,MQTT 有服务质量 QoS 分级。QoS 能够很容易确定某一个消息是否成功从客户端交付给 Broker 或者从 Broker 交付给客户端。这里也存在一些偶然性的情况,有些特定主题没有订阅者。如果这是一个问题,它取决于 Broker 如何处理这样的情况。例如,HiveMQ 的 Broker 有一个插件系统,它能够识别这种情况,并采取行动或仅仅是输出相应的日志到数据库供后续分析。为了减轻 Topic 主题的不灵活性,认真设计主题树(Topic Tree)并留有扩展的余地,在未来是很重要的。如果你遵循这些策略,那么 MQTT 会越用越好。

MQTT 与消息队列的区别

对于 MQTT,存在一些混淆的地方,它的名字使得它容易被当作消息队列来实现。这里要再次强调,MQTT 不是消息队列,在 IBM 的产品中,提供的消息队列被称为 MQserie。那么,MQTT 与传统的消息队列到底有什么区别?

1)消息队列会一直保存消息,直到消息被消费(Consume)

在使用消息队列时,每一条即将到来的消息都会被存放到消息队列中,直到消息被任何客户端取走(通常称为消费。否则,消息会一直存放在队列中,等待被消费。如果某条消息一直不被任何客户端所消费,这是不可能的,就好像 MQTT 的主题 Topic 没有任何客户端订阅的情况。

2)一条消息只能由一个客户端消费

这是一个很大的区别,在传统的消息队列中,一条消息仅能由一个消费者进行处理。因此,所有消费者之间的负载可以被分发到某个特定的队列上。而在 MQTT 上则完全相反,对于每一个订阅者,只要他们订阅了某个主题,那么他们都可以得到该主题的消息。

3)队列被命名,且必须以明确的方式创建

队列远远不及主题那么灵活。在使用队列之前,必须先使用一个单独的命令明确地创建队列。只有在队列创建之后,才可以在该队列上发布消息或消费消息。而 MQTT 的主题 Topic 是非常灵活的,可以动态地创建主题。

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2016-10/136404.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-21发表,共计2927字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中