发布/订阅(Pub/Sub)架构提供了一种灵活的、可伸缩的方式来构建能够处理许多连接的客户端的分布式系统。

MQTT基于发布/订阅架构,支持持久会话与服务质量QoS功能,实现了发布者与订阅者在空间、时间以及同步等方面的解耦。

发布/订阅模式

发布/订阅模式(Pub/Sub),是软件体系结构的消息传递模式,其特点是支持以解耦的方式在不同组件或系统之间进行通信

在这种模式中,有两个重要角色,分别是生成消息的发布者接收消息的订阅者

与传统C/S请求响应的通信模式相比,Pub/Sub模式,通过在中间增加代理服务器,使发布者和订阅者之间不需要进行端对端的通信,进而将消息的发布者与订阅者完全解耦。这种解耦使得通信过程更快、更高效。

Pub/Sub模式在三个方面实现了解耦,以实现最佳效率:

  1. 空间解耦: 发布者和订阅者不需要相互了解(例如,不交换IP地址和端口)。
  2. 时间解耦: 发布服务器和订阅服务器不需要同时运行。
  3. 同步解耦: 在发布或接收期间,不需要中断操作。

MQTT是遵循发布/订阅模式的消息传递协议之一

MQTT使用基于代理的模型,其中客户机连接到代理,消息发布到指定主题。然后,订阅者从代理订阅该主题并接收已发布的消息。

因而MQTT协议中也支持Pub/Sub模式中的解耦:

  1. MQTT只需要知道代理的主机名或I与端口号就可以发布和订阅消息,在空间上解耦了发布者和订阅者。
  2. MQTT通过支持持久会话和消息缓存,从而允许代理为未联机的客户机存储消息,在时间上解耦了发布者和订阅者。
  3. MQTT支持单个连接在多线程上同时分别进行订阅和发布,实现了同步解耦。

消息过滤

消息过滤是发布/订阅模式的一个重要功能,因为其控制订阅者能够接收到什么消息。

发布/订阅模式支持三种过滤选项,分别是主题过滤、内容过滤以及类型过滤。

主题过滤

在主题过滤模式中,代理根据主题对消息进行过滤。

主题是层次结构,层次之间用斜杠“/”分隔。

订阅者订阅特定的主题,代理根据主题的层次结构将消息路由到适当的订阅者。

优点

  1. 简单易用
  2. 灵活,允许分层的主题结构
  3. 高效,仅将消息发送给特定的订阅者(订阅该主题)

缺点

  1. 发布者和订阅者需要事先就主题层次结构达成一致
  2. 仅限于基于主题层次结构筛选消息

Pub/Sub 中基于主题的过滤用例:

MQTT的主题过滤

MQTT仅支持使用基于主题的消息过滤。

每条消息都包含一个主题,代理将消息发送给订阅该主题的每个订阅者。

内容过滤

在内容过滤模式中,代理根据消息内容对消息进行过滤,过滤方式是通过配置过滤器表达式。

订阅者通过订阅特定的过滤表达式来接收消息,代理根据消息的内容将消息路由到适当的订阅者。

MQTT不支持内容过滤模式。

优点

  1. 对接收消息提供更细粒度的控制。
  2. 允许基于消息内容而不仅仅是主题层次结构进行筛选。
  3. 更灵活,允许复杂的过滤表达式。

缺点

  1. 比主题过滤复杂,使用难。
  2. 发布者需要在消息中包含用于过滤的字段。
  3. 大量过滤时影响性能。

案例

适用于消息没有基于主题区分,订阅者对基于其内容的特定消息子集感兴趣。

例如,在物流应用程序中,订阅者可能只对接收有特定跟踪号码的包的消息感兴趣。订阅者将订阅一个过滤表达式,如“trace-number=‘123456’”,而代理将只向订阅者发送与该表达式匹配的消息。

类型过滤

在类型过滤模式中,代理根据消息的类型或类来进行过滤。

适用于过滤面向对象语言的类作为消息的情况,通过父类、类、子类等层次结构进行过滤。

订阅者订阅指定类型,代理将符合该类型以及子类的消息路由到订阅者。

优点

  1. 易于使用,特别是在使用面向对象语言时。
  2. 提供高度的灵活性和可扩展性。

缺点

  1. 仅限于基于消息类型的筛选。
  2. 发布者和订阅者需要事先就消息类型层次结构达成一致。

案例

类型过滤适用于消息被组织成类层次结构,订阅者对基于其类的特定类型或消息子集感兴趣

例如,订阅者对发布者产生的所有异常消息感兴趣,只需要订阅“Exception”类型,代理就可以将所有异常(包括继承该Exception类型的子类型)消息路由管理。

可伸缩性

在传统的C/S模式中,如果有大量的Client连接时,Server会限制连接的Client数量,这种模式会限制可伸缩性。

Pub/Sub模式通过以下几个功能提高可伸缩性:

Pub/Sub模式功能说明
以事件驱动的方式处理消息MQTT代理可以在不牺牲系统性能的情况下处理更多的并发连接。
消息缓存MQTT代理可以快速检索消息并传递给订阅者,无需额外处理。
智能消息路由MQTT代理确保消息仅传递给需要的订阅者,减少不必要的网络流量。

MQTT遵循Pub/Sub模式,具有这种模式拥有的可伸缩性,使得其非常适合于物联网。

尽管有这些优势,但是扩展到数百万的连接仍然对Pub/Sub模式的MQTT代理构成挑战。在这种情况下,可以使用集群代理节点将负载分布到多个服务器上,而负载均衡器可以确保流量均匀分布。

消息队列的区别

MQTT指的是IBM的MQ系列的产品Telemetry Transport,与“消息队列”没有任何关系。

下面是MQTT与消息队列的几点区别:

  1. 消息队列会存储每个传入的消息,直到客户端或使用者处理它们。如果没有客户端处理该消息,则该消息将一直保留在消息队列中。在MQTT中没有客户端订阅的主题上的会被丢弃。
  2. 消息队列中,消息只能由一个使用者处理。在MQTT中,订阅主题的每个订阅者都会获得消息。
  3. 队列必须命名,必须显式创建。只有在命名并创建队列之后,才能发布或使用消息。MQTT主题非常灵活,可以动态创建。