for my current project i need to consume messages from many destinations (from hundreds up to 20 or 30k) all destinations are topics. currently (for initial load tests) all messages are created localy on the same server, in a thread pool.
my current spring config uses an embedded activemq in a network of brokers (for clustering) and DefaultMessageListenerContainers (DMLCs) with a common TaskExecutor. while the number of destinations is very high, the throughput of each destination is relatively low.
My only requirement is that all messages are consumed as soon as possible.
My Config:
<bean id="connectionfactory" class="org.springframework.jms.connection.CachingConnectionFactory" destroy-method="destroy">
<property name="targetConnectionFactory">
<ref bean="amqConnectionFactory" />
</property>
</bean>
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost:61616?async=false&jms.dispatchAsync=false" />
<property name="userName" value="admin" />
<property name="password" value="admin" />
</bean>
<bean id="listenerThreadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="70" />
<property name="maxPoolSize" value="70" />
<property name="daemon" value="true" />
<property name="keepAliveSeconds" value="60" />
</bean>
<!-- Message Listener Container Template for Topics -->
<bean id="topiccontainertemplate" class="org.springframework.jms.listener.DefaultMessageListenerContainer" scope="prototype"
destroy-method="destroy">
<property name="autoStartup" value="false" />
<property name="connectionFactory" ref="connectionfactory" />
<property name="pubSubDomain" value="true" />
<property name="cacheLevelName" value="CACHE_CONSUMER" />
<property name="destinationName" value="default" />
<property name="maxMessagesPerTask" value="1" />
<property name="receiveTimeout" value="1" />
<property name="taskExecutor" ref="listenerThreadPoolTaskExecutor" />
</bean>
My code uses the application context as a DMLC-Factory and sets the final configuration of the container:
AbstractMessageListenerContainer container = context.getBean("simpletopiccontainertemplate", AbstractMessageListenerContainer.class);
container.setDestinationName(localEntity.getId().getDestination());
container.setMessageListener(mylistener);
container.start();
while we don't lose messages in this configuration the transition time for an individual message can be very long.
Q1: Is there a more efficient way to listen to a big number of destinations?
Q2: Are there possible improvements for my listener configuration?
Q3: Beside the DMLC i also tried the SimpleMessageListenerContainer but i couldn't get it to work. is there something wrong with my config?
<bean id="simpletopiccontainertemplate" class="org.springframework.jms.listener.SimpleMessageListenerContainer" scope="prototype"
destroy-method="destroy">
<property name="autoStartup" value="false" />
<property name="connectionFactory" ref="connectionfactory" />
<property name="destinationName" value="default" />
<property name="concurrency" value="1" />
<property name="pubSubDomain" value="true" />
<property name="taskExecutor" ref="listenerThreadPoolTaskExecutor" />
</bean>