Routing messages from one input queue to two output queues in ActiveMQ can be done in two different ways. Apache Camel, a powerful rule-based routing engine often used with ActiveMQ, is a typical choice. Virtual composite queue is another solution. Which to choose? The faster.
Apache Camel
Camel configuration I use:
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="activemq:INPUT-QUEUE"/>
<to uri="activemq:OUTPUT-1-QUEUE"/>
<to uri="activemq:OUTPUT-2-QUEUE"/>
</route>
</camelContext>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent" >
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost?create=false&waitForStart=10000" />
<property name="userName" value="${activemq.username}"/>
<property name="password" value="${activemq.password}"/>
</bean>
</property>
</bean>
</beans>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="activemq:INPUT-QUEUE"/>
<to uri="activemq:OUTPUT-1-QUEUE"/>
<to uri="activemq:OUTPUT-2-QUEUE"/>
</route>
</camelContext>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent" >
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost?create=false&waitForStart=10000" />
<property name="userName" value="${activemq.username}"/>
<property name="password" value="${activemq.password}"/>
</bean>
</property>
</bean>
</beans>
Benchmark took 3 minutes 31 seconds to send 10 thousand messages through Camel:
$ time ./amqinject INPUT-QUEUE 10000 0.651u 0.490s 3:31.43 0.5% 0+0k 0+0io 0pf+0w
Unfortunately “Number Of Pending Messages” was always about 1024 and amqinject gets blocked in send() call:
INFO | Usage Manager memory limit reached on queue://INPUT-QUEUE. Producers will be throttled to the rate at which messages are removed from this destination to prevent flooding it. See http://activemq.apache.org/producer-flow-control.html for more info
Virtual Composite Queue
Virtual destinations are configured in <broker> tag. Here is my configuration:
<destinations>
<queue physicalName="INPUT-QUEUE" />
<queue physicalName="OUTPUT-1-QUEUE" />
<queue physicalName="OUTPUT-2-QUEUE" />
</destinations>
<destinationInterceptors>
<virtualDestinationInterceptor>
<virtualDestinations>
<compositeQueue name="INPUT-QUEUE">
<forwardTo>
<queue physicalName="OUTPUT-1-QUEUE" />
<queue physicalName="OUTPUT-2-QUEUE" />
</forwardTo>
</compositeQueue>
</virtualDestinations>
</virtualDestinationInterceptor>
</destinationInterceptors>
<queue physicalName="INPUT-QUEUE" />
<queue physicalName="OUTPUT-1-QUEUE" />
<queue physicalName="OUTPUT-2-QUEUE" />
</destinations>
<destinationInterceptors>
<virtualDestinationInterceptor>
<virtualDestinations>
<compositeQueue name="INPUT-QUEUE">
<forwardTo>
<queue physicalName="OUTPUT-1-QUEUE" />
<queue physicalName="OUTPUT-2-QUEUE" />
</forwardTo>
</compositeQueue>
</virtualDestinations>
</virtualDestinationInterceptor>
</destinationInterceptors>
Amqinject never blocked and it took only 2 minutes 29 seconds to complete:
% time ./amqinject INPUT-QUEUE 10000 0.718u 0.539s 2:29.33 0.8% 0+0k 0+0io 0pf+0w