2014-10-31 06:20:28 -04:00
< html >
< head >
2014-11-19 03:44:57 -05:00
< title > ActiveMQ JMS Load Balanced Static Clustered Queue Example< / title >
2014-10-31 06:20:28 -04:00
< link rel = "stylesheet" type = "text/css" href = "../common/common.css" / >
< link rel = "stylesheet" type = "text/css" href = "../common/prettify.css" / >
< script type = "text/javascript" src = "../common/prettify.js" > < / script >
< / head >
< body onload = "prettyPrint()" >
< h1 > JMS Load Balanced Static Clustered One Way Queue Example< / h1 >
< p > This example demonstrates a JMS queue deployed on three different nodes. The three nodes are configured to form a one way cluster
from a < em > static< / em > list of nodes. < / p >
< p > A one way cluster is different from a symmetrical cluster in that each node is only connected to one another node in
a chain type fashion, so server 0 -> server 1 -> server 2< / p >
< p > We then create a consumer on the queue on each node, and we create a producer on only one of the nodes.< / p >
< p > We then send some messages via the producer, and we verify that < b > all< / b > consumers receive the sent messages
in a round-robin fashion.< / p >
2014-11-19 03:44:57 -05:00
< p > In other words, ActiveMQ < b > load balances< / b > the sent messages across all consumers on the cluster< / p >
2014-10-31 06:20:28 -04:00
< p > This example uses JNDI to lookup the JMS Queue and ConnectionFactory objects. If you prefer not to use
JNDI, these could be instantiated directly.< / p >
< p > Here's the relevant snippet from the server configuration, which tells the server to form a one way cluster between the three nodes
and to load balance the messages between the nodes. Note that we have set < em > allow-direct-connections-only< / em > to true,
this means that this server will only ever connect the address's specified in the list of connectors. ALso notice
that < em > max-hops< / em > is 2, this is because server 0 is not directly connected to server 2, 2 hops in fact, so we
allow any updates from servers up to 2 hops away< / p >
< pre class = "prettyprint" >
< code >
< 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> 2< /max-hops>
< static-connectors allow-direct-connections-only="true">
< connector-ref>server1-connector< /connector-ref>
< /static-connectors>
< /cluster-connection>
< / code >
< / pre >
2014-11-19 03:44:57 -05:00
< p > For more information on ActiveMQ load balancing, and clustering in general, please see the clustering
2014-10-31 06:20:28 -04:00
section of the user manual.< / p >
< h2 > Example step-by-step< / h2 >
< p > < i > To run the example, simply type < code > mvn verify< / code > from this directory< / i > < / p >
< ol >
< li > Get an initial context for looking up JNDI from server 0.< / li >
< pre class = "prettyprint" >
< code >
ic0 = getContext(0);
< / code >
< / pre >
< li > Look-up the JMS Queue object from JNDI< / li >
< pre class = "prettyprint" >
< code >
Queue queue = (Queue)ic0.lookup("/queue/exampleQueue");
< / code >
< / pre >
< li > Look-up a JMS Connection Factory object from JNDI on server 0< / li >
< pre class = "prettyprint" >
< code >
ConnectionFactory cf0 = (ConnectionFactory)ic0.lookup("/ConnectionFactory");
< / code >
< / pre >
< li > grab an initial connection and wait, in reality you wouldn't do it this way but since we want to ensure an
equal load balance we do this and then create 4 connections round robined< / li >
< pre class = "prettyprint" >
< code >
initialConnection = cf0.createConnection();
< / code >
< / pre >
< li > We create a JMS Connection connection0 which is a connection to server 0< / li >
< pre class = "prettyprint" >
< code >
connection0 = cf0.createConnection()
< / code >
< / pre >
< li > We create a JMS Connection connection0 which is a connection to server 1< / li >
< pre class = "prettyprint" >
< code >
connection1 = cf0.createConnection()
< / code >
< / pre >
< li > We create a JMS Connection connection0 which is a connection to server 2< / li >
< pre class = "prettyprint" >
< code >
connection2 = cf0.createConnection()
< / code >
< / pre >
< li > We create a JMS Session on server 0< / li >
< pre class = "prettyprint" >
< code >
Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE);
< / code >
< / pre >
< li > We create a JMS Session on server 1< / li >
< pre class = "prettyprint" >
< code >
Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
< / code >
< / pre >
< li > We create a JMS Session on server 1< / li >
< pre class = "prettyprint" >
< code >
Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
< / code >
< / pre >
< li > We start the connections to ensure delivery occurs on them< / li >
< pre class = "prettyprint" >
< code >
connection0.start();
connection1.start();
connection2.start();
< / code >
< / pre >
< li > We create JMS MessageConsumer objects on server 0 and server 1< / li >
< pre class = "prettyprint" >
< code >
MessageConsumer consumer0 = session0.createConsumer(queue);
MessageConsumer consumer2 = session2.createConsumer(queue);
MessageConsumer consumer3 = session3.createConsumer(queue);
< / code >
< / pre >
< li > We create a JMS MessageProducer object on server 0.< / li >
< pre class = "prettyprint" >
< code >
Session sendSession = getServerConnection(0, connection0, connection1, connection2).createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = sendSession.createProducer(queue);
< / code >
< / pre >
< li > We send some messages to server 0.< / li >
< pre class = "prettyprint" >
< code >
final int numMessages = 18;
for (int i = 0; i < numMessages ; i + + )
{
TextMessage message = session0.createTextMessage("This is text message " + i);
producer.send(message);
System.out.println("Sent message: " + message.getText());
}
< / code >
< / pre >
< li > We now consume those messages on *both* server 0 and server 1.
We note the messages have been distributed between servers in a round robin fashion.
2014-11-19 03:44:57 -05:00
ActiveMQ has < b > load balanced< / b > the messages between the available consumers on the different nodes.
ActiveMQ can be configured to always load balance messages to all nodes, or to only balance messages
2014-10-31 06:20:28 -04:00
to nodes which have consumers with no or matching selectors. See the user manual for more details.< / li >
JMS Queues implement point-to-point message where each message is only ever consumed by a
maximum of one consumer.
< pre class = "prettyprint" >
< code >
for (int i = 0; i < numMessages ; i + = 2 )
{
TextMessage message0 = (TextMessage)consumer0.receive(5000);
System.out.println("Got message: " + message0.getText() + " from node 0");
TextMessage message1 = (TextMessage)consumer1.receive(5000);
System.out.println("Got message: " + message1.getText() + " from node 1");
TextMessage message2 = (TextMessage)consumer2.receive(5000);
System.out.println("Got message: " + message2.getText() + " from node " + con2Node);
}
< / code >
< / pre >
< li > And finally (no pun intended), < b > always< / b > remember to close your JMS resources after use, in a < code > finally< / code > block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects< / li >
< pre class = "prettyprint" >
< code >
finally
{
if (initialConnection != null)
{
initialConnection.close();
}
if (connection0 != null)
{
connection0.close();
}
if (connection1 != null)
{
connection1.close();
}
if (connection2 != null)
{
connection2.close();
}
if (ic0 != null)
{
ic0.close();
}
}
< / code >
< / pre >
< / ol >
< / body >
< / html >