跳至主内容
版本:4.3

交换器 (Exchanges)

什么是交换机?

在 AMQP 0-9-1 中,交换机是发布者发布消息的实体,随后消息会被路由到一组队列或中。

与 AMQP 0-9-1 中的其他拓扑元素一样,交换机是由应用程序使用客户端库进行声明的。

交换机的目的是将流经它们的所有消息路由到一个或多个队列或其他交换机中。

交换机的类型和绑定属性用于实现路由逻辑。

交换机属于虚拟主机

与所有其他拓扑元素一样,每个交换机都属于一个虚拟主机。即使是仅存在于默认虚拟主机中的系统交换机也是如此。

当创建虚拟主机时,会在其中自动创建多个预声明的交换机。

交换机名称

每个交换机都必须有一个名称。

有一个特殊的交换机称为默认交换机(见下文),当它被指定为发布目标时,其名称为空字符串。

在其他上下文中,例如权限管理,同一个交换机可以称为 "amq.default",但在发布消息时不能使用此名称。

交换机类型

交换机可以有不同的类型。交换机类型控制其如何路由发布给它的消息。例如,一种交换机类型可以使用基于主题(模式)的路由,而另一种可以无条件地将所有消息路由到每个已绑定的队列。

RabbitMQ 随附多种交换机类型

交换机类型可由插件提供。

Fanout(扇出)

Fanout 交换机将发送到其中的每条消息的副本路由到绑定到它的每个队列、流或交换机。消息的路由键会被完全忽略。

请参阅教程 3 以了解如何使用此类型的交换机。

Topic(主题)

Topic 交换机使用消息路由键与绑定时使用的路由(绑定)键模式进行模式匹配。

为了进行路由,键通过 . 分隔为段。某些段由特定值填充,而其他段由通配符填充:* 匹配正好一个段,# 匹配零个或多个(包括多个)段。

例如:

  • 绑定(路由键)模式 "regions.na.cities.*" 将匹配消息路由键 "regions.na.cities.toronto""regions.na.cities.newyork",但不会匹配 "regions.na.cities",因为 * 是仅匹配一个段的通配符。
  • 绑定(路由键)模式 "audit.events.#" 将匹配 "audit.events""audit.events.users.signup""audit.events.orders.placed",但不会匹配 "audit.users",因为第二个段不匹配。
  • 绑定(路由键)模式 "#" 将匹配任何路由键,并使 Topic 交换机对于使用此类模式的绑定表现得像 Fanout 交换机一样。

请参阅教程 5 以了解如何使用此类型的交换机。

Direct(直连)

Direct 交换机使用绑定路由键的精确等价性将消息路由到一个或多个绑定的队列、流或交换机。

例如,绑定(路由)键 "abc" 将仅匹配 "abc"

请参阅教程 4 以了解如何使用此类型的交换机。

默认交换机

默认交换机是一种具有若干特殊属性的直连交换机。

  • 它始终存在(是预声明的)。
  • 对于 AMQP 0-9-1 客户端,其名称为空字符串 ("")。
  • 当声明队列时,RabbitMQ 会自动使用队列名称作为路由键将该队列绑定到默认交换机。

这为 AMQP 0-9-1 应用程序提供了一种机制,使其能够方便地仅使用队列名称“直接”发布到队列,尽管底层仍然涉及直连交换机。

提示

默认交换机因其特殊属性而被使用。它不应被用作应用程序显式创建绑定的“常规”交换机。

在需要直连交换机和自定义拓扑的情况下,请考虑声明并使用单独的直连交换机。

Local Random 交换机

Local Random 是一种专门的交换机类型,在单独的文档指南中有介绍。

JMS Topic 交换机

JMS Topic 交换机是为了实现RabbitMQ JMS 客户端的特定 JMS 功能而引入的。

什么是绑定?

交换机在声明时不知道任何队列或流。最初声明的交换机是一个空的命名路由表。

为了用某些路由规则填充该表,必须将队列、流或另一个交换机(见下文)绑定到该交换机。换句话说,应用程序必须在交换机与队列或流之间创建绑定。

绑定具有以下属性:

  • 源名称:添加此绑定的交换机的名称。
  • 目标名称:目标队列、流或另一个交换机的名称。
  • 目标类型(对于队列和流为 queue,对于交换机到交换机绑定为 exchange)。
  • 可选的参数映射,某些交换机类型可以使用它(例如 Headers 交换机)。

绑定持久性

绑定从其源和目标继承持久性。因此,绑定可以是:

  • 完全持久:其交换机和目标/队列/流均为持久的。
  • 半持久:在实践中,这意味着其交换机是持久的,而其目标/队列/流是瞬时的。
  • 完全瞬时:其交换机和目标/队列/流均为瞬时的。

对半持久和完全瞬时绑定的支持将在未来被取消。

当绑定与瞬时经典队列一起使用时,绑定持久性很重要。

警告

当托管非复制(经典)队列的节点停止时,其上所有的瞬时队列和半持久绑定都将被删除。

在大规模拓扑的情况下,这可能需要时间。当节点重新联机且应用程序重新连接时,半持久和瞬时绑定可能会被同时删除和重新添加,这可能导致不一致的绑定状态和令人困惑的路由行为。

为避免上述问题,请仅使用持久(复制或非复制)队列(可选择使用合理的短TTL)和流,并限制瞬时队列的使用(例如,仅在使用默认交换机发布时使用)。

预声明的交换机

根据 AMQP 0-9-1 规范

根据 AMQP 0-9-1 规范,每个虚拟主机包含若干预声明的交换机:

  • 默认交换机。
  • 多个 amq.* 交换机,每种类型一个,例如 amq.fanoutamq.topic

系统交换机

交换机属性

交换机有几个可以在声明时指定的关键属性:

持久性

就像队列一样,交换机可以是持久的或瞬时的。然而,瞬时交换机在实践中很少使用。

根据经验,考虑使用持久交换机的原因如下:

  • 具有瞬时或客户端特定状态的应用程序很少需要(或使用)自定义交换机,而是依赖于预声明的交换机(如 amq.topic)。
  • 在 4.x 系列的后续版本中,当 Khepri 成为唯一支持的元数据存储时,将取消对瞬时(非持久)实体的支持。

自动删除

自动删除的交换机在它们的最后一个绑定被移除时会被删除。

这要求至少存在此类绑定(已创建);从未绑定的交换机不会通过此机制被删除。

可选参数

可选交换机参数(因其在 AMQP 0-9-1 协议中的字段名称而被称为 "x-arguments")是客户端在声明交换机时可以提供的任意键/值对映射(字典)。

该映射被特定功能和交换机类型使用,例如备用交换机和 Headers 交换机。

这些可选参数也可以通过策略进行设置。

提示

如果可选参数可以通过策略设置,请始终优先考虑使用策略,而不是在应用程序代码中硬编码这些值。

可选交换机参数可以通过不同方式设置:

  • 使用策略应用于一组交换机(推荐)。
  • 在声明时按每个交换机进行设置。

前者更加灵活、非侵入式,不需要修改应用程序或重新部署,因此强烈推荐给大多数用户。注意,某些可选参数只能由客户端提供,因为它们无法动态更改,且必须在声明时已知。然而,此类限制主要适用于队列和流,而非交换机。

客户端提供可选参数的方式因客户端库而异,但通常是在声明交换机的函数(方法)中位于 durableauto_delete 等参数旁边的参数。

可选参数与策略定义键的优先级

当客户端提供的 x-arguments策略中提供了相同的键时,前者具有优先权。

然而,如果同时也使用了操作员策略,则操作员策略也优先于客户端提供的参数。操作员策略是一种保护机制,会覆盖客户端提供的值和用户策略值。

对于数值,将使用两者中的较小值。如果应用程序需要或选择使用较低的值,操作员策略将允许这样做。但是,不能使用高于操作员策略定义的值。

使用操作员策略为与资源使用相关的应用程序控制参数(例如,磁盘空间峰值使用量)引入护栏。

交换机到交换机绑定

除了队列和流,交换机可以使用 RabbitMQ 中名为交换机到交换机绑定(简称 E2E)的 AMQP 0-9-1 协议扩展绑定到另一个交换机。

然后应用程序发布到源交换机,源交换机会将消息路由到目标交换机。

注意

出于效率考虑,发布到具有 E2E 绑定的源交换机的消息将仅被路由一次,使用源交换机和绑定到它的所有目标交换机上所有可用绑定的总集。

换句话说,E2E 绑定不会重新发布消息,它们是一种尊重源交换机和目标交换机类型的路由扩展。

这意味着目标交换机的入站消息速率指标不会更新。目标队列和流的指标将会更新,无论它们是绑定到源交换机还是目标交换机。

备用交换机

备用交换机是一项允许无法路由消息(因为没有合适的绑定)的交换机将路由委托给不同交换机的功能。

备用交换机在执行拓扑迁移或收集不可路由消息时非常有用。

系统交换机

RabbitMQ 提供了多个内置的交换机,用于日志记录和审计目的:

这两个交换机使得开发自定义日志收集和审计应用程序成为可能,且这些应用程序仅需要 AMQP 0-9-1 客户端库。

© . This site is unofficial and not affiliated with VMware.