1. Visual Destinations

  1.1 概述

  虚拟Destination用来创建逻辑Destinations,客户端可以通过它来产生和消费消息,它会把消息映射到物理Destinations。ActiveMQ支持两种方式:

  1. 虚拟主题(Virtual Topics)

  2. 组合Destinations (Composite Destinations)

  1.2 为何使用虚拟主题

  ActiveMQ中,topic只有在持久订阅下才会持久化,持久订阅时,每个订阅者,都相当于一个queue的客户端,它会收取所有消息,这种情况下存在两个问题:

  1. 同一个应用内的consumer端负载均衡的问题,也就是同一个应用上的一个持久订阅者不能使用多个consumer来共同承担消息处理功能,因为每个consumer都会获取所有消息。

  2. 同一应用内的consumer端的failover问题:由于只能使用单个的持久订阅者,如果这个订阅者出错,则应用就无法处理消息了,系统的健壮性不高。

  为了解决这两个问题,ActiveMQ中实现了虚拟的Topic的功能。

  1.3 如何使用虚拟主题

  1. 对于消息发布者来说,就是一个正常的Topic,名称以VirtualTopic开头。例如

  VirtualTopic.Orders.代码示例如下:

Topic destination = session.createTopic("VirtualTopic.Orders");

  2. 对于消息接收端来说,是一个队列,不同应用里面应使用不同的前缀作为队列的名称,即可表明自己的身份,即可实现消费端应用的分组。

  例如Consumer.A.VritualTopic.Orders,说明它是名称A的消费端,同理Consumer.B.VritualTopic.Orders表示时一个名称为B的客户端,可以在同一个应用里面使用多个consumer消费此queue,则可以实现上面两个功能。

  又因为不同应用使用的queue名称不同(前缀不同),所以不同的应用中都可以接收到全部的消息,每个客户端相当于一个持久订阅者,而且这个客户端可以使用多个消费者来共同承担消费任务,代码示例如下:

 Destination destiantion = session.createQueue("Consumer.A.VirtualTopic.Orders“);

  完整得测试代码如下:

  消息发送者

package com.wangx.activemq.topic;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class TopicSender {

    public static void main(String[] args) throws JMSException {
ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE); //创建虚拟主题,加前缀VirtualTopic
Topic topic = session.createTopic("VirtualTopic.myTopic");
MessageProducer producer = session.createProducer(topic);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
connection.start(); for (int i = 0; i < 30; i++) {
TextMessage textMessage = session.createTextMessage("topic消息===" + i);
producer.send(textMessage);
}
session.commit();
connection.close(); }
}

  A客户端代码(只有一个消费者)

package com.wangx.activemq.topic;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
public class QR1 { public static void main(String[] args) throws JMSException {
ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//创建队列
Destination destination = session.createQueue("Consumer.A.VirtualTopic.myTopic");
MessageConsumer consumer = session.createConsumer(destination); consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("Consumer.A.接收到得消息:" + textMessage.getText());
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
}); }
}

  B客户端代码,有两个消费者

package com.wangx.activemq.topic;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class QR2 {
public static void main(String[] args) throws JMSException {
ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//创建队列
Destination destination = session.createQueue("Consumer.B.VirtualTopic.myTopic");
final MessageConsumer consumer = session.createConsumer(destination);
final MessageConsumer messageConsumer = session.createConsumer(destination);
//模拟多个consumer消费一个queue
new Thread(new Runnable() {
@Override
public void run() {
try {
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("Consumer.B-->consumer接收到消息:" + textMessage.getText());
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
} catch (JMSException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
messageConsumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("Consumer.B-->messageConsumer接收到消息:" + textMessage.getText());
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
} catch (JMSException e) {
e.printStackTrace();
}
}
}).start();
}
}

  在接收消息之前,应该先运行一下consumer客户端,将消费者注册到Broker中。

  3. 默认虚拟主题得前缀是:VirtualTopic.>

  自定义消费虚拟地址默认格式:Consumer.*.VirtualTopic.>

  自定义消费虚拟地址可以改,比如下面的配置就把它修改了。

  xml配置如下

<broker xmlns="http:/activemq.apache.org/schema/core">

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

  配置之后将consumer端的相应前缀修改即可。

2. Mirrored Queues

  2.1 概述

   ActiveMQ中每个queue中的消息只能被一个consumer消费,然而,有时候你可能希望能够监视生产者和消费者之间的消息流。你可以通过Virtual Destinations来建立一个virtual queue 来把消息发送到多个queues中。但是,为系统中没给queue都进行如此配置可能会很麻烦。

  2.1使用

  ActiveMQ支持Mirrored Queues。Broker会把发送到某个queue的所有消息都转发到一个名称类似的topic,因此监控程序只需要订阅这个mirrored queue topic。为了启用Mirrored Queues,首先将Broker Service的useMirroredQueues属性设置成true,然后可以通过destinationInterceptors设置其他属性,如:mirror topic的前缀,缺省是:“VirtualTopic.Mirror.".

    比如修改后的配置如下

<destinationInterceptors>
<mirroredQueue copyMessage="true" postfix=".qmirror" prefix=""/>
</destinationInterceptors>

  在我的配置中并没有配置配置前缀,但是一定需要配置copyMessage="true",查看控制台如下

  存在默认前缀的topic,此时只需要用一个消费者去消费该topic中的消息就可以了。

3. Per Destination Policies

  ActiveMQ支持多种不同的策略,来单独配置每一个Destination,它的属性很多,可以参考官方文档:

  http://activemq.apache.org/per-destination-policies.html

  官方文档最后还给出了一个demo做参考。

最新文章

  1. log4j的简单应用(转载)
  2. Java中的Property类
  3. php常用代码(一)
  4. PHP发送邮件。
  5. 实现类似微信的延迟加载的Fragment——LazyFragment
  6. 二十六个月Android学习工作总结
  7. 问题解决——Group Box控件遮挡其它控件
  8. SQL Server Database 维护计划创建一个完整的备份策略
  9. 201521123070 《JAVA程序设计》第5周学习总结
  10. MariaDB日志审计 帮你揪出内个干坏事儿的小子
  11. 项目中使用sass预处理器
  12. 如何禁用Chrome / Firefox /IE浏览器的Cookie
  13. 背水一战 Windows 10 (80) - 本地化
  14. JavaScript学习 - 基础(一)
  15. 配置阿里云的金融云上的rsync
  16. bzoj 4919 [Lydsy1706月赛]大根堆 set启发式合并+LIS
  17. Ubuntu安装redis和redis-php扩展
  18. vue与django中预防CSRF
  19. 使用DIDatepicker
  20. BZOJ4373 算术天才⑨与等差数列(线段树)

热门文章

  1. VB入门在线视频教程大全学习
  2. idea--IntelliJ IDEA隐藏不想看到的文件或文件夹
  3. CentOS 7 安装配置MySQL
  4. [CodeForces]1006F Xor Path
  5. S3C6410 LCD Overlay Test Program
  6. vue路由传值params和query的区别
  7. windows服务器剪贴板不能共用的解决办法
  8. 洛谷 1156 dp
  9. nutch的一些基础整理
  10. DebugBar v7.0.2 注册码