0

I have a 2 server ActiveMQ Artemis cluster setup with discovery using JGroups working correctly. Then in my applications the ConnectionFactory is created via the ActiveMQJMSClient:

final ActiveMQConnectionFactory cf = ActiveMQJMSClient.createConnectionFactory(
    "jgroups://test-cluster?file=jgroups-file-ping.xml&connectionLoadBalancingPolicyClassName=org.apache.activemq.artemis.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy", "test-cluster");

Then the producers and consumers are handled with Spring. However, when Spring creates 10 consumers on start-up I'm seeing that all 10 consumers go to the same Artemis server.

Here is the Spring JMS Configuration:

@Bean 
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() throws Exception {
    final ConnectionFactory cf = getActiveMQConnectionFactory();
    final DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(cf);
    factory.setConcurrency("10-20");
    factory.setSessionTransacted(true);
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);

    return factory;
}

Then on application startup I call this within the JmsListenerConfigurer:

public static void registerEndPoint(final JmsListenerEndpointRegistrar registrar,
    String endPointName, String dest, MessageListener listener) {
    final SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();

    endpoint.setId(endPointName);
    endpoint.setDestination(dest);
    endpoint.setMessageListener(listener);
    registrar.registerEndpoint(endpoint);
}

Is there a way of setting this up so that there are 5 consumers on each Artemis server?

Samyel
  • 139
  • 5
  • How many actual connections is the Spring component creating? If it's only creating one connection then that would explain why all the clients are on a single broker. – Justin Bertram Mar 26 '18 at 14:26
  • I only create one ConnectionFactory, but it then creates 10 consumers using that ConnectionFactory. – Samyel Mar 27 '18 at 10:38
  • As the name implies, the "connectionLoadBalancingPolicyClassName" applies to connections, not consumers. If you only create a single connection you will only be connected to a single broker. All the consumers, producers, etc. created on that connection will be on the corresponding broker. To be clear, messages in an Artemis cluster will be moved to prevent consumer starvation. – Justin Bertram Mar 27 '18 at 15:22
  • This makes sense. In that case the issue is with spring only creating a single connection from the connection factory, is there a way to tune this? We see that messages aren't moved in the Artemis cluster if there is at least one application connected to each broker. This causes scenarios where the majority of messages are going to a single Artemis broker, but only one application is connected to it, with the other applications connected to the other broker doing no processing. – Samyel Mar 28 '18 at 10:59
  • The cluster will always prefer local consumers to remote ones. It will only redistribute messages if there are no local consumers. However, you can force message load-balancing by using specifying STRICT for the message-load-balancing (https://activemq.apache.org/artemis/docs/latest/clusters.html#configuring-cluster-connections). That said, if you only have 2 applications then I would suggest you don't actually need a cluster. Artemis has good performance so you could probably meet your performance goals will just one broker. – Justin Bertram Mar 28 '18 at 15:30

1 Answers1

0

Spring's DefaultJmsListenerContainerFactory has a cache level that can be changed to CACHE_NONE,CACHE_CONNECTION,CACHE_SESSION or CACHE_AUTO.

I had to set it to CACHE_NONE for Spring to create more than a single connection in the connection factory.

Samyel
  • 139
  • 5