【问题标题】:Routing to virtual destinations inside ActiveMQ broker路由到 ActiveMQ 代理内的虚拟目的地
【发布时间】:2017-06-02 15:42:55
【问题描述】:

我有一个 activemq 配置,其中我有一个虚拟目标和一个普通主题

我想根据消息头中的 JMSType 将所有 JMS 消息路由到目的地(VirtualTopic.Notifications)到 2 个队列(VirtualTopic.SMS、VirtualTopic.EMAIL)。

我希望正常的 Topic(VirtualTopic.gps) 像往常一样工作。

这是我对activemq.xml的配置。此处创建了 Consumer.SMS.VirtualTopic 和 Consumer.EMAIL.VirtualTopic。

    <destinations>
        <queue physicalName="Consumer.SMS.VirtualTopic" />
        <queue physicalName="Consumer.EMAIL.VirtualTopic" />
    </destinations>

    <destinationInterceptors>
      <virtualDestinationInterceptor>
        <virtualDestinations>
          <compositeQueue name="VirtualTopic.Notifications" forwardOnly="false">
            <forwardTo>
              <filteredDestination selector="JMSType = 'SMS'" queue="Consumer.SMS.VirtualTopic"/>
              <filteredDestination selector="JMSType = 'EMAIL'" queue="Consumer.EMAIL.VirtualTopic"/>
            </forwardTo>
          </compositeQueue>
        </virtualDestinations>
      </virtualDestinationInterceptor>
    </destinationInterceptors>

虽然消费者和主题 (VirtualTopic.gps) 是从服务器端代码创建的。

    private static MessageProducer getTopicProducer(String topicName) throws JMSException {
    MessageProducer producer = topicProducers.get(topicName);

    if (producer == null) {
        logger.info("Creating message producer for Topic : {}", topicName);
        Destination destination = session.createTopic(topicName);

        List<String> queueNames = PropertyReader
                .getPropertyStringList("jms.topic.consumer.list", JMSProducer.properties);
        if (queueNames != null) {
            for (String queueName : queueNames) { 
                Queue virtualQueue = session.createQueue(queueName);
                MessageConsumer con = session.createConsumer(virtualQueue);
                con.close();
            }
        }

        producer = session.createProducer(destination);
        topicProducers.put(topicName, producer);
    }

    return producer;
    }

到 VirtualTopic.Notifications 的所有消息都被路由到 2 个不同的队列,消费者可以从各自的队列中获取消息

但问题是所有发送到 VirtualTopic.gps 的消息都被过滤了,消费者无法消费 gps 消息。

【问题讨论】:

  • 首先;您正在谈论主题,但我在您的配置中没有看到任何主题,您的所有目的地都是队列的,要使用主题,您必须使用 更新您的配置并使用
  • 关于您谈论哪个消费者的目的地? 但其他主题的消费者没有收到消息。
  • 恢复到哪个配置?? 当我恢复我的配置时,除了 SMS 之外的主题的消费者,EMAIL 正在工作。
  • Hassen Bennour:嘿,我的意思是所有消息都通过 并被过滤。但所需的行为应该类似于发布到 VirtualTopic 的消息。通知应该过滤到 SMS 和 EMAILS。我还有一个主题 VirtualTopic.gps 消费者没有收到消息
  • 你是如何配置这个 VirtualTopic.gps 的?您将消息作为目的地发送给它?

标签: activemq messagebroker jms-topic virtual-topic


【解决方案1】:

非常感谢哈森..

添加此行&lt;virtualTopic name="&gt;" selectorAware="false" /&gt; 到 activemq.xml 就成功了。

    <destinationInterceptors>
        <virtualDestinationInterceptor>
            <virtualDestinations>
                <compositeQueue name="VirtualTopic.Notifications"
                    forwardOnly="false">
                    <forwardTo>
                        <filteredDestination selector="JMSType = 'SMS'"
                            queue="Consumer.SMS.VirtualTopic" />
                        <filteredDestination selector="JMSType ='EMAIL'"
                            queue="Consumer.EMAIL.VirtualTopic" />
                    </forwardTo>
                </compositeQueue>
                <virtualTopic name=">" selectorAware="false" />
            </virtualDestinations>
        </virtualDestinationInterceptor>
    </destinationInterceptors>

【讨论】:

    【解决方案2】:

    下面的例子展示了如何设置一个元素 在 XML 配置中,以便在向 MY.QUEUE 发送消息时 然后真的是转发到物理队列FOO和topic 酒吧。

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

    默认情况下,订阅者不能直接从 复合队列或主题 - 它只是一个逻辑结构。鉴于 上面的配置,订阅者只能消费来自 FOO 的消息 和酒吧;但不是 MY.QUEUE。可以更改此行为以实现 用例,例如通过将相同的消息发送到队列来监视队列 通知主题(窃听),通过设置可选设置 forwardOnly 属性为 false。

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

    发送到 IncomingOrders 的消息将全部复制并转发到 通知,在被放置在物理 IncomingOrders 之前 排队等待订阅者消费。

    看这里http://activemq.apache.org/virtual-destinations.html

    使用您的实际配置,您只能从队列的 SMS & EMAIL 中使用,如果您想从 Notifications 中使用,则需要设置 forwardOnly="false"

    更新: 试试这个代码:

    import javax.jms.Connection;
    import javax.jms.JMSException;
    import javax.jms.MessageProducer;
    
    import org.apache.activemq.ActiveMQConnectionFactory;
    import org.apache.activemq.ActiveMQMessageConsumer;
    import org.apache.activemq.ActiveMQSession;
    import org.apache.activemq.command.ActiveMQTextMessage;
    
    public class SimpleSenderConsumerVirtualTopic {
    
        public static void main(String[] args) throws JMSException {
            Connection conn = null;
            try {
                ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory();
                conn = cf.createConnection( );
                ActiveMQSession session = (ActiveMQSession) conn.createSession(false,
                        ActiveMQSession.AUTO_ACKNOWLEDGE);
                ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer) session
                        .createConsumer(session.createQueue("Consumer.A.VirtualTopic.gps"));
                MessageProducer producer = session.createProducer(session.createTopic("VirtualTopic.gps"));
                conn.start();
                ActiveMQTextMessage msg = (ActiveMQTextMessage) session.createTextMessage("VirtualTopic.gps test");
                producer.send(msg);
                msg = null;
                while ((msg = (ActiveMQTextMessage) consumer.receive(5000)) != null) {
                    System.out.println("Received message is: " + msg.getText());
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (conn != null) {
                    try {
                        conn.close();
                    } catch (Exception e) {
                    }
                }
            }
        }
    }
    

    并添加:

    <destinationInterceptors>
          <virtualDestinationInterceptor>
            <virtualDestinations>
              <compositeQueue name="VirtualTopic.Notifications" forwardOnly="false">
                <forwardTo>
                  <filteredDestination selector="JMSType = 'SMS'" queue="Consumer.SMS.VirtualTopic"/>
                  <filteredDestination selector="JMSType = 'EMAIL'" queue="Consumer.EMAIL.VirtualTopic"/>
                </forwardTo>
              </compositeQueue>
              <virtualTopic name=">"  selectorAware="false" />
            </virtualDestinations>
          </virtualDestinationInterceptor>
        </destinationInterceptors>
    

    【讨论】:

    • No Hassen,我不想从 VirtualTopics.Notifications 消费。我还有一个主题(VirtualTopic.gps),消费者没有收到消息。
    • 将此添加到目标拦截器配置解决了问题。
    • 出于这个原因,我觉得奇怪的是,您使用给定的回复来发布您的回复并就地接受它
    猜你喜欢
    • 2011-06-24
    • 1970-01-01
    • 2011-02-02
    • 2020-06-04
    • 2021-03-25
    • 1970-01-01
    • 2017-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多