郑重提示,本文转载自http://shift-alt-ctrl.iteye.com/blog/2065436

ActiveMQ提供了虚拟通道的特性(Virtual Destination),它允许一个逻辑通道(logical destination)映射成一个或者多个物理通道(physical destination);它可以非常灵活的解决"消息整合"方面的问题,它可以实现:

1) 提供了VirtualTopic特性,可以让一个订阅者的消息列表,作为Queue来消费。

2) 提供了Composite特性,可以把一个逻辑通道中的消息,转发到任意多的物理通道中。

一. VirtualTopic

Topic最大的限制就是同一个ClientId的订阅者,任何时刻只能有一个活跃。所以我们在分布式部署时,就会很麻烦,比如一个应用部署成多个实例,且它们都有相同的Topic Consumer配置,那么意味着

一个实例部署成功后,其它的实例都会因为无法订阅Topic而导致故障;同时也意味着,如果这个Topic Consumer失效后,我们不能自动让其他Consumer的接管它。但是Queue却没有这些限制,因为Queue可以同时有任意多个消费者,它们可以并发的消费消息,从而实现“负载均衡”。如果我们期望Topic也能如此,那么可以用VirtualTopic。

  1. <broker xmlns="http://activemq.apache.org/schema/core">
  2. <destinationInterceptors>
  3. <virtualDestinationInterceptor>
  4. <virtualDestinations>
  5. <virtualTopic name=">" prefix="VConsumers.*." selectorAware="false"/>
  6. </virtualDestinations>
  7. </virtualDestinationInterceptor>
  8. </destinationInterceptors>
  9. </broker>

对于所有的VirtualTopic,它们的namespace一定是"VirtualTopic.",Broker将会根据此namespace来判定逻辑通道是否为VirtualTopic,反过来说,如果你希望一个逻辑通道是一个VirtualTopic,那么它必须以“VirtualTopic.”作为前缀。比如“VirtualTopic.order”,那么它就是一个VirtualTopic,它的物理通道名称为"order"。

对于Producer端,需要按照正常的Topic发送消息,通道名称为逻辑通道全名:

  1. Topic topic = session.createTopic("VirtualTopic.order");
  2. MessageProducer producer = session.createProducer(topic);
  3. //producer.send(message);

VirtualTopic对Consumer而言,是一个逻辑的Queue,Queue的全名有上述配置文件中的“prefix” + Client标识 + 逻辑虚拟通道;假如“Client标识”为"dbcenter"【相当于ClientId】,用来订阅Order消息,那么最终逻辑Queue的全名为:"VConsumers.dbcenter.VirtualTopic.order",其中需要注意prefix中的"*"占位符就是用来替换“Client标识”的;Broker端默认的prefix为"Consumer.*."。当然我们还可以postfix【后缀】,不过通常没有必要。

  1. Queue queue = session.createQueue("VConsumers.dbcenter.VirtualTopic.order");
  2. MessageConsumer consumer = session.createConsumer(queue);

对于Order通道而言,“dbcenter”相当于是一个订阅者;Broker将dbcenter订阅的消息转发到了“VConsumers.dbcenter.VirtualTopic.order”队列中;最重要的一点,这个虚拟Queue完全具有队列的所有特性,它的Consumer可以并行消费。

其中还有一个重要的参数"selectorAware",它表示从Topic中将消息转发给Queue时,是否关注Consumer的selector情况。如果为false,那么Topic中的消息全部转发给Queue,否则只会转发匹配Queue Consumer的selector的消息。需要非常注意,当selectorAware为true时,如果消息不匹配任何selector或者Queue中没有任何Consumer活跃,那么消息将不会转发给Queue。

VirtualTopic仍然可以被正常的订阅者消费,即:

  1. Topic topic = session.createTopic("VirtualTopic.order");
  2. TopicSubscriber subscriber = session.createDurableSubscriber(topic,"dbcenter");

同时需要注意,VirtualTopic只会转发“Client标识”注册之后的消息,且即使Queue消费了消息,VirtualTopic中的消息仍然不会被删除(看起来仍然是Dequeued=0),对于Broker而言,逻辑Queue不被认为是一个“Durable Subscriber”,只有真正的Subscriber消费消息后,Topic中的消息才会Dequeue。不过消息Dequeue后,不会影响Queue中的消息,因为这是基于Copy的。

到目前为止,我尚不清楚,如果VirtualTopic中没有真正的Subscriber,这些消息该如何Dequeue。

当真正的subscriber和Queue都同时存在VirtualTopic中的时候,而且你的broker架构采用了“forward-brige”结构,那么你需要增加如下配置来避免消息的重复转发问题。在forward-brige架构中,任何通道中的消息都会forward到其他network node中(其他broker上),当然这个虚拟的Queue的消息也不例外。

  1. <networkConnectors>
  2. <networkConnector uri="static://(tcp://localhost:61617)">
  3. <excludedDestinations>
  4. <!-- prefix和VirtualTopic保持一致
  5. <queue physicalName="VConsumer.*.VirtualTopic.>"/>
  6. </excludedDestinations>
  7. </networkConnector>
  8. </networkConnectors>

二. Composite Destinations

复合通道,它允许一条消息在多个物理通道间转发,就像一个通道映射成多个一样(one-many);比如复合通道A,映射成B和C,那么发往A的消息会同时转发给B和C,那么消费者可以直接通过B或者C获取消息;

这是一种实现消息复制转发、通道映射的便捷办法。复合通道包括CompositeQueue和CompositeTopic两种。

  1. <broker persistent="false" useJmx="false" xmlns="http://activemq.apache.org/schema/core">
  2. <destinationInterceptors>
  3. <virtualDestinationInterceptor>
  4. <virtualDestinations>
  5. <compositeQueue name="order">
  6. <forwardTo>
  7. <queue physicalName="order.dbcenter" />
  8. <topic physicalName="order.statistic" />
  9. </forwardTo>
  10. </compositeQueue>
  11. <!--
  12. <compositeTopic name="order" forwardOnly="false">
  13. <forwardTo>
  14. <queue physicalName="order.dbcenter" />
  15. <topic physicalName="order.statistic" />
  16. </forwardTo>
  17. </compositeTopic>
  18. -->
  19. </virtualDestinations>
  20. </virtualDestinationInterceptor>
  21. </destinationInterceptors>
  22. </broker>

上述配置forwardOnly属性表示发往CompositeQueue中的消息是否“仅仅转发,而不本地保留”,如果forwardOnly为true,那么消息将不会在order队列中保留,即order队列中不会有任何消息。如果为false,那么消息将会转发完成后,添加到order中,消费者仍然可以消费order队列中的消息。无论是Compsite通道还是转发的通道,它们和普通的通道没有任何区别,开发者仍然可以像使用普通的通道一样使用它们(消费消息和发送消息)。

很多时候,我们希望在转发消息时,能够使用selector,此时我们可以使用filteredDestination,这样我们可以消息转发时控制消息。

  1. <compositeQueue name="MY.QUEUE">
  2. <forwardTo>
  3. <filteredDestination selector="orderType = 1" queue="food.order"/>
  4. <filteredDestination selector="status = 1" topic="order.statistic"/>
  5. </forwardTo>
  6. </compositeQueue>

【转】ActiveMQ与虚拟通道的更多相关文章

  1. 使用 ActiveMQ 实现JMS 异步调用

    目录 简介 启动 ActiveMQ 服务器 查看控制台 ActiveMQ 的消息通道 Queue Topic 比较 开发生产者和消费者 开发服务端(消费者) 开发客户端(生产者) 参考 简介 服务之间 ...

  2. 某企业桌面虚拟化项目-Citrix虚拟桌面解决方案

    xxx桌面虚拟化项目Citrix解决方案 xxx桌面虚拟化项目 Citrix解决方案 1 项目背景 秉承"尊重个性.创造价值.贡献于社会"的企业理念和开拓创新的精神,xxx所制造. ...

  3. 分布式消息中间件Rabbit Mq的了解与使用

    MQ(消息队列)作为现代比较流行的技术,在互联网应用平台中作为中间件,主要解决了应用解耦.异步通信.流量削锋.服务总线等问题,为实现高并发.高可用.高伸缩的企业应用提供了条件. 目前市面比较流行的消息 ...

  4. Java的消息机制

    Java消息机制 1.问: 什么是 Java 消息服务?答: Java 消息服务(Java Message Service,JMS) API 是一个用于访问企业消息传递系统的 API.是 Java 2 ...

  5. Neutron 理解 (1): Neutron 所实现的虚拟化网络 [How Netruon Virtualizes Network]

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  6. mstsc 远程序桌面登录的 c#开发

    public AxMSTSCLib.AxMsRdpClient rdpClient; rdpClient = new AxMSTSCLib.AxMsRdpClient(); rdpClient.Doc ...

  7. Linux tcpdump命令详解

    tcpdump官网:http://www.tcpdump.org/ 转载于:http://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.ht ...

  8. 黄聪:远程序桌面登录的.NET(C#)开发

    MSTSCLib.dll和MsTscAxWrapper.dll下载:LibDll.rar 远程序桌面登录的.NET开发,可以使用MSTSCLib.dll和MsTscAxWrapper.dll两个转换过 ...

  9. http2协议翻译(转)

    超文本传输协议版本 2 IETF HTTP2草案(draft-ietf-httpbis-http2-13) 摘要 本规范描述了一种优化的超文本传输协议(HTTP).HTTP/2通过引进报头字段压缩以及 ...

随机推荐

  1. json的遍历

    第一种json结构: var jsongood = {"goods":[{"parentId":"null","productId ...

  2. ajax使用json

    json是什么什么的废话不说了,去百度吧.我这里介绍一下我为何要使用json.我使用ajax响应返回值时,项目中需求要返回多个值,不能只返回一个值.这时候就想起来用到json了.这可能只是json的一 ...

  3. 虚拟机在 OpenStack 里没有共享存储条件下的在线迁移[转]

    原文链接:http://www.ibm.com/developerworks/cn/cloud/library/1508_wangyx_openstacklivemigrate/ 迁移(Migrati ...

  4. chd校内选拔赛题目+题解

    题目链接   A. Currency System in Geraldion 有1时,所有大于等于1的数都可由1组成.没有1时,最小不幸的数就是1. #include<iostream> ...

  5. i++与++i区别使用

    中心:使用变量自增或者处减使用尽量使用++i与--i,而不要去使用i++与i-- ++i与--i可以做左值也可以做右值,而i++与i--只能做右值. 对于基础类型i++与++i结果相同,但是i++肯定 ...

  6. gem install bundler

    http://stackoverflow.com/questions/7483515/rake-aborted-no-such-file-to-load-bundler-setup-rails-3-1 ...

  7. maven打包配置

    maven打包配置,到底要打包哪些文件,如何配置?? <build> <finalName>weatherAdminSys</finalName> <plug ...

  8. aop代理方式引起的spring注入bean(实现类)与获取bean(实现类)出错

    描述: 现象一 :A 为 接口,AImpl 为 A 的实现类,且 AImpl 受 aop 扫描,且 aop 无特殊配置   此时若:Spring 中 注入 AImpl 类型的bean,获取一样     ...

  9. iOS摇一摇功能、震动功能、简单的摇动动画、生成二维码图片与发送短信等几个功能

    有一个开锁的功能,具体的需求就类似于微信的"摇一摇"功能:摇动手机,手机震动,手机上的锁的图片摇动一下,然后发送开锁指令.需求简单,但用到了许多方面的知识. 1.摇一摇 相对这是最 ...

  10. FR javascript 时间设置上个月最后一天后当月最后一天

    //设置上月最后一天 var date1 =new Date(); date1.setDate(1); //first day; date1.setMonth(date1.getMonth()); / ...