ActiveMQ学习笔记(14)----Destination高级特性(二)
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高级特性(二)的更多相关文章
- Python 学习笔记 之 02 - 高级特性总结
切片 语法: li.[x:y:z] li为list.tuple等数据类型,x为开始进行切片的位置,y为切片停止的位置(不包含y),z为xy切片后的结果里,每间隔z个元素输出一次结果. x默认为0 ...
- ActiveMQ中的Destination高级特性(一)
---------------------------------------------------------------------------------------- Destination ...
- 分布式-信息方式-ActiveMQ的Destination高级特性1
ActiveMQ的Destination高级特性 Destination高级特性----->Composite Destinations 组合队列Composite Destinations : ...
- ActiveMQ学习笔记(5)——使用Spring JMS收发消息
摘要 ActiveMQ学习笔记(四)http://my.oschina.net/xiaoxishan/blog/380446 中记录了如何使用原生的方式从ActiveMQ中收发消息.可以看出,每次 ...
- 基于.net的分布式系统限流组件 C# DataGridView绑定List对象时,利用BindingList来实现增删查改 .net中ThreadPool与Task的认识总结 C# 排序技术研究与对比 基于.net的通用内存缓存模型组件 Scala学习笔记:重要语法特性
基于.net的分布式系统限流组件 在互联网应用中,流量洪峰是常有的事情.在应对流量洪峰时,通用的处理模式一般有排队.限流,这样可以非常直接有效的保护系统,防止系统被打爆.另外,通过限流技术手段,可 ...
- C++ 学习笔记(一些新特性总结3)
C++ 学习笔记(一些新特性总结3) public.protected 和 private 继承 public 继承时,基类的存取限制是不变的. class MyClass { public: // ...
- Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法
Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法 Ext.Net GridPanel可以进行Group操作,例如: 如何启用Grouping功能呢?只需要在Grid ...
- SQL反模式学习笔记14 关于Null值的使用
目标:辨别并使用Null值 反模式:将Null值作为普通的值,反之亦然 1.在表达式中使用Null: Null值与空字符串是不一样的,Null值参与任何的加.减.乘.除等其他运算,结果都是Null: ...
- golang学习笔记14 golang substring 截取字符串
golang学习笔记14 golang substring 截取字符串golang 没有java那样的substring函数,但支持直接根据 index 截取字符串mystr := "hel ...
- mybatis学习笔记(14)-查询缓存之中的一个级缓存
mybatis学习笔记(14)-查询缓存之中的一个级缓存 标签: mybatis mybatis学习笔记14-查询缓存之中的一个级缓存 查询缓存 一级缓存 一级缓存工作原理 一级缓存測试 一级缓存应用 ...
随机推荐
- CentOS 7.1 下载,安装,配置
CentOS(全称 Community Enterprise Operating System)是 RHEL 源代码再编译的产物. 2014年初,CentOS 宣布加入 Red Hat. CentOS ...
- Apache负载均衡配置
使用mod_proxy 配置Apache负载均衡 1.安装apache ./configure --prefix=/usr/local/apache2 –enable-so make &&am ...
- Python介绍与学习
Python是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年. Python是纯粹的自由软件, 源代码和解释器CPy ...
- sklearn学习8-----GridSearchCV(自动调参)
一.GridSearchCV介绍: 自动调参,适合小数据集.相当于写一堆循环,自己设定参数列表,一个一个试,找到最合适的参数.数据量大可以使用快速调优的方法-----坐标下降[贪心,拿当前对模型影响最 ...
- 再次理解JS的prototype,__proto__和constructor
个人总结: 下面这篇文章很好的讲解了js原型,原型链,个人的总结是要记住这三个属性 prototype.__proto__和constructor 首先明确,js中一切都是对象object(A). ( ...
- ES6 学习6 数组的扩展
本章学习要点: 扩展运算符 Array.from() Array.of() 数组实例的 copyWithin() 数组实例的 find() 和 findIndex() 数组实例的 fill() 数组实 ...
- CF833B The Bakery (线段树+DP)
题目大意:给你一个序列(n<=35000),最多分不大于m块(m<=50),求每个块内不同元素的数量之和的最大值 考试的时候第一眼建图,没建出来,第二眼贪心 ,被自己hack掉了,又随手写 ...
- [USACO18JAN] Lifeguards S (线段树:扫描线面积)
扫描线裸题没什么好说的 注意空间不要开小了!!! #include <cstdio> #include <cstring> #include <algorithm> ...
- linux之资料重定向
標準輸入 (stdin) :代碼為 0 ,使用 < 或 << : 標準輸出 (stdout):代碼為 1 ,使用 > 或 >> : 標準錯誤輸出(stderr):代 ...
- input只能输入数字或两位小数
/** * [只能输入数字和两位小数] * 举例:<input type="text" onkeyup="num(this)" size="10 ...