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做参考。

ActiveMQ学习笔记(14)----Destination高级特性(二)的更多相关文章

  1. Python 学习笔记 之 02 - 高级特性总结

    切片 语法:  li.[x:y:z]  li为list.tuple等数据类型,x为开始进行切片的位置,y为切片停止的位置(不包含y),z为xy切片后的结果里,每间隔z个元素输出一次结果.  x默认为0 ...

  2. ActiveMQ中的Destination高级特性(一)

    ---------------------------------------------------------------------------------------- Destination ...

  3. 分布式-信息方式-ActiveMQ的Destination高级特性1

    ActiveMQ的Destination高级特性 Destination高级特性----->Composite Destinations 组合队列Composite Destinations : ...

  4. ActiveMQ学习笔记(5)——使用Spring JMS收发消息

      摘要 ActiveMQ学习笔记(四)http://my.oschina.net/xiaoxishan/blog/380446 中记录了如何使用原生的方式从ActiveMQ中收发消息.可以看出,每次 ...

  5. 基于.net的分布式系统限流组件 C# DataGridView绑定List对象时,利用BindingList来实现增删查改 .net中ThreadPool与Task的认识总结 C# 排序技术研究与对比 基于.net的通用内存缓存模型组件 Scala学习笔记:重要语法特性

    基于.net的分布式系统限流组件   在互联网应用中,流量洪峰是常有的事情.在应对流量洪峰时,通用的处理模式一般有排队.限流,这样可以非常直接有效的保护系统,防止系统被打爆.另外,通过限流技术手段,可 ...

  6. C++ 学习笔记(一些新特性总结3)

    C++ 学习笔记(一些新特性总结3) public.protected 和 private 继承 public 继承时,基类的存取限制是不变的. class MyClass { public: // ...

  7. Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法

    Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法 Ext.Net GridPanel可以进行Group操作,例如: 如何启用Grouping功能呢?只需要在Grid ...

  8. SQL反模式学习笔记14 关于Null值的使用

    目标:辨别并使用Null值 反模式:将Null值作为普通的值,反之亦然 1.在表达式中使用Null: Null值与空字符串是不一样的,Null值参与任何的加.减.乘.除等其他运算,结果都是Null: ...

  9. golang学习笔记14 golang substring 截取字符串

    golang学习笔记14 golang substring 截取字符串golang 没有java那样的substring函数,但支持直接根据 index 截取字符串mystr := "hel ...

  10. mybatis学习笔记(14)-查询缓存之中的一个级缓存

    mybatis学习笔记(14)-查询缓存之中的一个级缓存 标签: mybatis mybatis学习笔记14-查询缓存之中的一个级缓存 查询缓存 一级缓存 一级缓存工作原理 一级缓存測试 一级缓存应用 ...

随机推荐

  1. Function 和 eval 知识点总结

    1 Function 1.1 函数的创建方式 1 函数声明 2 函数表达式 3 new Function // 1 function foo() {} // 2 var foo = function( ...

  2. <Android Framework 之路>Android5.1 Camera Framework(一)

    Android5.0 Camera Framework 简介 CameraService启动 CameraService是在MediaServer启动过程中进行的 main_mediaserver.c ...

  3. ZBrush中Mrgb、Rgb和M的使用

    ZBrush®软件工具架中所有的命令选项都是我们平时较为常用的,位于工具架的中间位置,有一个Mrgb.Rgb和M选项它们所表示的是材质及颜色,那么,在Zbrush中只要选择相应的选项,就可以同时绘制材 ...

  4. hp soap扩展最全说明,附天气预报调用的例子

    自从php5开始,我们可以不用通过php nusoap来创建php soap web service 和调用 soap了,php5内置了 soap扩展.只需要在php.ini中开启soap的exten ...

  5. 利用请求的JSON数据创建图形图层

    先看效果图: 包含三个部分:信息窗口(标题是要素的某个属性信息,其余是感兴趣的属性信息).图上图形按照某一属性大小不一显示,图例 1.创建底图用于存放以上三部分: "esri/Map&quo ...

  6. Vue系列(三):组件及数据传递、路由、单文件组件、vue-cli脚手架

    上一篇:Vue系列(二):发送Ajax.JSONP请求.Vue生命周期及实例属性和方法.自定义指令与过渡 一. 组件component 1. 什么是组件? 组件(Component)是 Vue.js ...

  7. Java代码实现MySQL数据库的备份与还原

    通常在MySQL数据库的备份和恢复的时候,多是采用在cmd中执行mysql命令来实现. 例如: mysqldump -h127.0.0.1 -uroot -ppass test > d:/tes ...

  8. URAL 1517 Freedom of Choice

    Freedom of Choice Time Limit: 2000ms Memory Limit: 32768KB This problem will be judged on Ural. Orig ...

  9. 解析如何利用ElasticSearch和Redis检索和存储十亿信息

    如果从企业应用的生存率来看,选择企业团队信息作为主要业务,HipChat的起点绝非主流:但是如果从赚钱的角度上看,企业市场的高收益确实值得任何公司追逐,这也正是像JIRA和Confluence这样的智 ...

  10. .NET开源项目一览