NMS.ActiveMQ 虚拟目的地

虚拟目的地 允许我们创建逻辑目的地,客户端可以使用这些目的地进行生产和消费,但这些目的地映射到一个或多个 物理目的地。它使我们能够提供更灵活的松散耦合消息传递配置。

虚拟主题

发布订阅 背后的理念很棒。允许生产者与消费者分离,以便他们甚至不知道有多少消费者对他们发布的消息感兴趣。JMS 规范定义了对持久主题的支持,但它们有一些局限性,我们将在下面描述......

JMS 持久主题的局限性

一个 JMS 持久订阅者 MessageConsumer 是使用唯一的 JMS 客户端 ID 和持久订阅者名称创建的。为了符合 JMS 规范,在任何时间点,对于一个 JMS 客户端 ID,只能有一个 JMS 连接处于活动状态,并且对于一个客户端 ID 和订阅者名称,只能有一个消费者处于活动状态。即,只有一个线程可以从给定的逻辑主题订阅者主动消费。这意味着我们无法实现

  • 消息的负载均衡。
  • 如果运行那个消费者线程的进程死亡,订阅者的快速故障转移。

现在,JMS 中的队列语义提供了一种可靠的方式,可以在多个消费者之间负载均衡工作 - 允许许多线程、进程和机器用于处理消息。然后,我们拥有像 消息组 这样的复杂粘性负载均衡技术,以在保持顺序的同时负载均衡和并行化工作。

对于每个逻辑主题订阅者都有物理队列的另一个好处是,我们可以通过 JMX 监控队列深度,以监控系统性能,同时还可以浏览这些物理队列。

虚拟主题来拯救

虚拟主题背后的理念是,生产者以通常的 JMS 方式发送到主题。消费者可以继续使用 JMS 规范中的主题语义。但是,如果主题是虚拟的,消费者可以从逻辑主题订阅的物理队列中消费,允许许多消费者在许多机器和线程上运行以负载均衡负载。

例如,假设我们有一个名为 VirtualTopic.Orders 的主题。(其中前缀 VirtualTopic. 表示它是一个虚拟主题)。并且我们逻辑上想要将订单发送到系统 A 和 B。现在,使用常规的持久主题,我们将为 clientID_A 和“A”创建一个 JMS 消费者,以及为 clientID_B 和“B”创建一个 JMS 消费者。

使用虚拟主题,我们只需直接消费到队列 Consumer.A.VirtualTopic.Orders 即可成为系统 A 的消费者,或者消费到 Consumer.B.VirtualTopic.Orders 即可成为系统 B 的消费者。

现在,我们可以为每个系统拥有一个消费者池,然后这些消费者竞争系统 A 或 B 的消息,以便为系统 A 处理的所有消息都恰好处理一次,同样地,为系统 B 处理的所有消息都恰好处理一次。

自定义开箱即用的默认值

开箱即用的默认值如上所述。即,唯一可用的虚拟主题必须在 VirtualTopic.> 命名空间内,并且消费者队列的命名方式为 Consumer.*.VirtualTopic.>

您可以配置它以使用您想要的任何命名约定。以下 示例 显示了如何使所有主题都成为虚拟主题。以下示例使用名称 > 来表示“匹配所有主题”。您可以使用此通配符在不同的层次结构中应用不同的虚拟主题策略。

<destinationInterceptors>
  <virtualDestinationInterceptor>
    <virtualDestinations>
      <virtualTopic name=">" prefix="VirtualTopicConsumers.*." selectorAware="false"/>
    </virtualDestinations>
  </virtualDestinationInterceptor>
</destinationInterceptors>

请注意,将主题设为虚拟主题确实会在将消息发送到主题时增加少量的 CPU 负载,但这相对较小。

选项 默认值 描述
selectorAware false 只有与现有订阅者之一匹配的消息才会实际被分发。使用此选项可以防止在独占消费者使用选择器时累积不匹配的消息
local false 如果为 true,则不要将通过网络接收的消息进行扇出
concurrentSend false 如果为 true,则使用执行器进行扇出,以便发送并行发生。这允许日志文件批处理写入,从而减少磁盘 IO(5.12)
transactedSend false 如果为 true,则对扇出发送使用事务,以便只有一个磁盘同步。如果不存在客户端事务,则会创建一个本地代理事务(5.13)

复合目的地

复合目的地允许对单个目的地进行一对多关系;主要用例是用于 复合队列。例如,当消息发送到队列 A 时,您可能希望将其也转发到队列 B 和 C 以及主题 D。然后,复合目的地是将虚拟目的地映射到其他物理目的地集合。在这种情况下,映射是在代理端完成的,客户端不知道目的地之间的映射。这与客户端侧的 复合目的地 不同,在客户端侧的复合目的地中,客户端使用 URL 符号来指定必须将消息发送到的实际物理目的地。

以下 示例 显示了如何在 XML 配置中设置 <compositeQueue/> 元素,以便当消息发送到 MY.QUEUE 时,它实际上被转发到物理队列 FOO 和主题 BAR

<destinationInterceptors>
  <virtualDestinationInterceptor>
    <virtualDestinations>
      <compositeQueue name="MY.QUEUE">
        <forwardTo>
          <queue physicalName="FOO" />
          <topic physicalName="BAR" />
        </forwardTo>
      </compositeQueue>
    </virtualDestinations>
  </virtualDestinationInterceptor>
</destinationInterceptors>

默认情况下,订阅者无法直接从复合队列或主题消费消息 - 它只是一个逻辑结构。鉴于上述配置,订阅者只能从 FOOBAR 消费消息;但不能从 MY.QUEUE 消费消息。

此行为可以更改,以实现诸如通过将相同的消息发送到通知主题(线路监听)来监视队列之类的用例,方法是将可选设置的 forwardOnly 属性设置为 false。

<compositeQueue name="IncomingOrders" forwardOnly="false">
  <forwardTo>
    <topic physicalName="Notifications" />
  </forwardTo>
</compositeQueue>

发送到 IncomingOrders 的消息都将被复制并转发到 Notifications,然后放置在物理 IncomingOrders 队列中,供订阅者消费。

在未定义或设置为 trueforwardOnly 属性的情况下,compositeQueuecompositeTopic 之间没有逻辑区别 - 它们可以互换使用。只有当复合目的地通过使用 forwardOnly 成为物理目的地时,compositeTopic/compositeQueue 的选择才会对行为产生影响。

使用过滤的目的地

从 Apache ActiveMQ 4.2 开始,您现在可以使用选择器来定义虚拟目的地。

您可能希望创建一个虚拟目的地,它将消息转发到多个目的地,但首先应用选择器来决定消息是否真的必须转到特定目的地。

以下示例显示了发送到虚拟目的地 MY.QUEUE 的消息将在选择器匹配时被转发到 FOOBAR

<destinationInterceptors>
  <virtualDestinationInterceptor>
    <virtualDestinations>
      <compositeQueue name="MY.QUEUE">
        <forwardTo>
          <filteredDestination selector="odd = 'yes'" queue="FOO"/>
          <filteredDestination selector="i = 5" topic="BAR"/>
        </forwardTo>
      </compositeQueue>
    </virtualDestinations>
  </virtualDestinationInterceptor>
</destinationInterceptors>

避免代理网络中的重复消息

您必须确保在使用基于队列的订阅者和非基于队列的订阅者(即,如果对虚拟主题有正常的主题订阅者)同时订阅虚拟主题时,发送到 Consumer.*.VirtualTopic.> 目的地的消息不会被转发。如果您在代理网络中使用虚拟主题,则在使用默认网络配置时,您可能会收到重复的消息。这是因为网络节点不仅会转发发送到虚拟主题的消息,还会转发关联的物理队列。要解决此问题,您应该禁用转发关联物理队列上的消息。

以下是如何执行此操作的示例

<networkConnectors>
  <networkConnector uri="static://(tcp://127.0.0.1:61617)">
    <excludedDestinations>
      <queue physicalName="Consumer.*.VirtualTopic.>"/>
    </excludedDestinations>
  </networkConnector>
</networkConnectors>

Apache、ActiveMQ、Apache ActiveMQ、Apache 羽毛徽标和 Apache ActiveMQ 项目徽标是 Apache 软件基金会的商标。版权所有 © 2024,Apache 软件基金会。根据 Apache 许可证 2.0 授权。