This examples demonstrates a symmetric cluster set-up with ActiveMQ.
ActiveMQ has extremely flexible clustering which allows you to set-up servers in many different topologies.
The most common topology that you'll perhaps be familiar with if you are used to application server clustering is a symmetric cluster.
With a symmetric cluster, the cluster is homogeneous, i.e. each node is configured the same as every other node, and every node is connected to every other node in the cluster.
By connecting node in such a way, we can, from a JMS point of view, give the impression of distributed JMS queues and topics.
The configuration used in this example is very similar to the configuration used by ActiveMQ when installed as a clustered profile in JBoss Application Server.
To set up ActiveMQ to form a symmetric cluster we simply need to mark each server as clustered
and we need to define a cluster-connection
in broker.xml
.
The cluster-connection
tells the nodes what other nodes to make connections to.
With a cluster-connection
each node that we connect to can either be specified
indivually, or we can use UDP discovery to find out what other nodes are in the cluster.
Using UDP discovery makes configuration simpler since we don't have to know what nodes are available at any one time.
Here's the relevant snippet from the server configuration, which tells the server to form a cluster with the other nodes:
<cluster-connection name="my-cluster">
<address>jms</address>
<connector-ref>netty-connector</connector-ref>
<retry-interval>500</retry-interval>
<use-duplicate-detection>true</use-duplicate-detection>
<forward-when-no-consumers>true</forward-when-no-consumers>
<max-hops>1</max-hops>
<discovery-group-ref discovery-group-name="my-discovery-group"/>
</cluster-connection>
In this example we create a symmetric cluster of six live nodes, and we also pair each live node with it's own backup node. (A backup node is not strictly necessary for a symmetric cluster).
In this example will we will demonstrate this by deploying a JMS topic and Queue on all nodes of the cluster , sending messages to the queue and topic from different nodes, and verifying messages are received correctly by consumers on different nodes.
For more information on configuring ActiveMQ clustering in general, please see the clustering section of the user manual.
To run the example, simply type mvn verify -Pexample
from this directory
ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithHA("231.7.7.7", 9876);
Queue queue = new ActiveMQQueue("exampleQueue");
Topic topic = ActiveMQJMSClient.createActiveMQTopic("exampleTopic");
connection0 = cf.createConnection();
connection1 = cf.createConnection();
connection2 = cf.createConnection();
connection3 = cf.createConnection();
connection4 = cf.createConnection();
connection5 = cf.createConnection();
connection0.start();
connection1.start();
connection2.start();
connection3.start();
connection4.start();
connection5.start();
Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session session3 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session session4 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
Session session5 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer subscriber0 = session0.createConsumer(topic);
MessageConsumer subscriber1 = session1.createConsumer(topic);
MessageConsumer subscriber2 = session2.createConsumer(topic);
MessageConsumer subscriber3 = session3.createConsumer(topic);
MessageConsumer subscriber4 = session4.createConsumer(topic);
MessageConsumer subscriber5 = session5.createConsumer(topic);
MessageConsumer consumer0 = session0.createConsumer(queue);
MessageProducer producer2 = session2.createProducer(null);
final int numMessages = 500;
for (int i = 0; i < numMessages; i++)
{
TextMessage message1 = session2.createTextMessage("Topic message 1");
producer2.send(topic, message1);
TextMessage message2 = session2.createTextMessage("Queue message 1");
producer2.send(queue, message2);
}
for (int i = 0; i < numMessages; i++)
{
TextMessage received0 = (TextMessage)subscriber0.receive(5000);
if (received0 == null)
{
return false;
}
TextMessage received1 = (TextMessage)subscriber1.receive(5000);
if (received1 == null)
{
return false;
}
TextMessage received2 = (TextMessage)subscriber2.receive(5000);
if (received2 == null)
{
return false;
}
TextMessage received3 = (TextMessage)subscriber3.receive(5000);
if (received3 == null)
{
return false;
}
TextMessage received4 = (TextMessage)subscriber4.receive(5000);
if (received4 == null)
{
return false;
}
TextMessage received5 = (TextMessage)subscriber5.receive(5000);
if (received5 == null)
{
return false;
}
TextMessage received6 = (TextMessage)consumer0.receive(5000);
if (received6 == null)
{
return false;
}
}
finally
{
if (connection0 != null)
{
connection0.close();
}
if (connection1 != null)
{
connection1.close();
}
if (connection2 != null)
{
connection2.close();
}
}