Author: jmesnil
Date: 2010-01-12 08:23:13 -0500 (Tue, 12 Jan 2010)
New Revision: 8793
Modified:
trunk/docs/user-manual/en/examples.xml
trunk/examples/jms/client-side-load-balancing/readme.html
trunk/examples/jms/client-side-load-balancing/src/org/hornetq/jms/example/ClientSideLoadBalancingExample.java
Log:
updated client-side load-balancing example
* rewrite the example to show clearly load-balancing behaviour
(without round-robin the message consumption)
* update example + doc to make it clear load-balancing is
at the session level for a single JMS connection
Modified: trunk/docs/user-manual/en/examples.xml
===================================================================
--- trunk/docs/user-manual/en/examples.xml 2010-01-12 09:38:23 UTC (rev 8792)
+++ trunk/docs/user-manual/en/examples.xml 2010-01-12 13:23:13 UTC (rev 8793)
@@ -74,11 +74,11 @@
connections given an IP address using the JMX management
API.</para>
</section>
<section>
- <title>Client Side Load-Balancing</title>
+ <title>Client-Side Load-Balancing</title>
<para>The <literal>client-side-load-balancing</literal>
example demonstrates how
- subsequent connections created from a JMS
<literal>ConnectionFactory</literal> can
+ sessions created from a single JMS
<literal>Connection</literal> can
be created to different nodes of the cluster. In other words it
demonstrates how
- HornetQ does client side load balancing of connections across the
cluster.</para>
+ HornetQ does client-side load-balancing of sessions across the
cluster.</para>
</section>
<section id="examples.clustered.grouping">
<title>Clustered Grouping</title>
Modified: trunk/examples/jms/client-side-load-balancing/readme.html
===================================================================
--- trunk/examples/jms/client-side-load-balancing/readme.html 2010-01-12 09:38:23 UTC (rev
8792)
+++ trunk/examples/jms/client-side-load-balancing/readme.html 2010-01-12 13:23:13 UTC (rev
8793)
@@ -8,7 +8,7 @@
<body onload="prettyPrint()">
<h1>JMS Client-Side Load-Balancing Example</h1>
- <p>This example demonstrates how subsequent connections created from a JMS
Connection Factory can be created
+ <p>This example demonstrates how sessions created from a single JMS Connection
can be created
to different nodes of the cluster. In other words it demonstrates how HornetQ does
<b>client side load balancing</b> of
connections across the cluster.</p>
<p>The particular load-balancing policy can be chosen to be random,
round-robin or user-defined. Please see the user
@@ -44,58 +44,28 @@
<code>ConnectionFactory connectionFactory =
(ConnectionFactory)initialContext.lookup("/ConnectionFactory");</code>
</pre>
- <li>We create three connections, since we are using round-robin
load-balancing this should
- result in each connection being connected to a different node of the
cluster</li>
+ <li>We create a single connection</li>
<pre class="prettyprint">
<code>
- connectionA = connectionFactory.createConnection();
-
- connectionB = connectionFactory.createConnection();
-
- connectionC = connectionFactory.createConnection();
+ connection = connectionFactory.createConnection();
</code>
</pre>
- <li>We create a JMS Session on each of those connections</li>
+ <li>We create 3 JMS Sessions from the same connection. Since we are using
round-robin
+ load-balancing this should result in each sessions being connected to a
different node of the cluster</li>
<pre class="prettyprint">
<code>
- Session sessionA = connectionA.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- Session sessionB = connectionB.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- Session sessionC = connectionC.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Session sessionA = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Session sessionB = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Session sessionC = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
</code>
</pre>
- <li>We start the connections to ensure delivery occurs on them</li>
- <pre class="prettyprint">
- <code>
- connectionA.start();
-
- connectionB.start();
-
- connectionC.start();
- </code>
- </pre>
-
- <li>We create JMS MessageConsumer objects on the sessions</li>
- <pre class="prettyprint">
- <code>
- MessageConsumer consumerA = sessionA.createConsumer(queue);
-
- MessageConsumer consumerB = sessionB.createConsumer(queue);
-
- MessageConsumer consumerC = sessionC.createConsumer(queue);
- </code>
- </pre>
-
<li>We create JMS MessageProducer objects on the sessions</li>
<pre class="prettyprint">
<code>
MessageProducer producerA = sessionA.createProducer(queue);
-
MessageProducer producerB = sessionB.createProducer(queue);
-
MessageProducer producerC = sessionC.createProducer(queue);
</code>
</pre>
@@ -108,47 +78,39 @@
for (int i = 0; i < numMessages; i++)
{
TextMessage messageA = sessionA.createTextMessage("A:This is text
message " + i);
-
producerA.send(messageA);
-
System.out.println("Sent message: " + messageA.getText());
TextMessage messageB = sessionB.createTextMessage("B:This is text
message " + i);
-
producerB.send(messageB);
-
System.out.println("Sent message: " + messageB.getText());
TextMessage messageC = sessionC.createTextMessage("C:This is text
message " + i);
-
producerC.send(messageC);
-
System.out.println("Sent message: " + messageC.getText());
}
</code>
</pre>
-
- <li>We now consume the messages from each node. The connections must be on
different nodes
- since if they shared nodes then the consumers would receive the messages sent
from different connections.</li>
+
+ <li>We start the connection to consume messages</li>
<pre class="prettyprint">
<code>
- for (int i = 0; i < numMessages; i ++)
- {
- TextMessage messageA = (TextMessage)consumerA.receive(5000);
-
- System.out.println("Got message: " + messageA.getText() + "
from node A");
-
- TextMessage messageB = (TextMessage)consumerB.receive(5000);
-
- System.out.println("Got message: " + messageB.getText() + "
from node B");
-
- TextMessage messageC = (TextMessage)consumerC.receive(5000);
-
- System.out.println("Got message: " + messageC.getText() + "
from node C");
- }
+ connection.start();
</code>
</pre>
+ <li>We consume messages from the 3 session, one at a time.<br>
+ We try to consume one more message than expected from each session. If
+ the session were not properly load-balanced, we would be missing a
+ message from one of the sessions at the end.</li>
+ <pre class="prettyprint">
+ <code>
+ consume(sessionA, queue, numMessages, "A");
+ consume(sessionB, queue, numMessages, "B");
+ consume(sessionC, queue, numMessages, "C");
+ </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">
Modified:
trunk/examples/jms/client-side-load-balancing/src/org/hornetq/jms/example/ClientSideLoadBalancingExample.java
===================================================================
---
trunk/examples/jms/client-side-load-balancing/src/org/hornetq/jms/example/ClientSideLoadBalancingExample.java 2010-01-12
09:38:23 UTC (rev 8792)
+++
trunk/examples/jms/client-side-load-balancing/src/org/hornetq/jms/example/ClientSideLoadBalancingExample.java 2010-01-12
13:23:13 UTC (rev 8793)
@@ -14,6 +14,7 @@
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
@@ -24,14 +25,11 @@
import org.hornetq.common.example.HornetQExample;
/**
- * This example demonstrates how subsequent connections created from a single connection
factory can be load
+ * This example demonstrates how sessions created from a single connection can be load
* balanced across the different nodes of the cluster.
*
* In this example there are three nodes and we use a round-robin client side
load-balancing
* policy.
- *
- * Note that the three nodes are deliberately not connected as a cluster so we don't
have any server-side
- * load balancing going on.
*
* @author <a href="tim.fox(a)jboss.com>Tim Fox</a>
*/
@@ -47,12 +45,8 @@
{
InitialContext initialContext = null;
- Connection connectionA = null;
+ Connection connection = null;
- Connection connectionB = null;
-
- Connection connectionC = null;
-
try
{
// Step 1. Get an initial context for looking up JNDI from server 0
@@ -65,114 +59,80 @@
ConnectionFactory connectionFactory =
(ConnectionFactory)initialContext.lookup("/ConnectionFactory");
// Wait a little while to make sure broadcasts from all nodes have reached the
client
- Thread.sleep(2000);
+ Thread.sleep(5000);
- // Step 4. We create three connections, since we are using round-robin
load-balancing this should
- // result in each connection being connected to a different node of the cluster
+ // Step 4. We create a single connection
+ connection = connectionFactory.createConnection();
+
+ // Step 5. We create 3 JMS Sessions from the same connection. Since we are using
round-robin
+ // load-balancing this should result in each sessions being connected to a
different node of the cluster
+ Session sessionA = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Session sessionB = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Session sessionC = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- connectionA = connectionFactory.createConnection();
-
- connectionB = connectionFactory.createConnection();
-
- connectionC = connectionFactory.createConnection();
-
- // Step 5. We create a JMS Session on each of those connections
- Session sessionA = connectionA.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- Session sessionB = connectionB.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- Session sessionC = connectionC.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- // Step 6. We start the connections to ensure delivery occurs on them
- connectionA.start();
-
- connectionB.start();
-
- connectionC.start();
-
- // Step 7. We create JMS MessageConsumer objects on the sessions
- MessageConsumer consumerA = sessionA.createConsumer(queue);
-
- MessageConsumer consumerB = sessionB.createConsumer(queue);
-
- MessageConsumer consumerC = sessionC.createConsumer(queue);
-
- // Step 8. We create JMS MessageProducer objects on the sessions
+ // Step 6. We create JMS MessageProducer objects on the sessions
MessageProducer producerA = sessionA.createProducer(queue);
-
MessageProducer producerB = sessionB.createProducer(queue);
-
MessageProducer producerC = sessionC.createProducer(queue);
- // Step 9. We send some messages on each producer
-
+ // Step 7. We send some messages on each producer
final int numMessages = 10;
for (int i = 0; i < numMessages; i++)
{
TextMessage messageA = sessionA.createTextMessage("A:This is text
message " + i);
-
producerA.send(messageA);
-
System.out.println("Sent message: " + messageA.getText());
TextMessage messageB = sessionB.createTextMessage("B:This is text
message " + i);
-
producerB.send(messageB);
-
System.out.println("Sent message: " + messageB.getText());
TextMessage messageC = sessionC.createTextMessage("C:This is text
message " + i);
-
producerC.send(messageC);
-
System.out.println("Sent message: " + messageC.getText());
}
+
+ // Step 8. We start the connection to consume messages
+ connection.start();
+
+ // Step 9. We consume messages from the 3 session, one at a time.
+ // We try to consume one more message than expected from each session. If
+ // the session were not properly load-balanced, we would be missing a
+ // message from one of the sessions at the end.
+ consume(sessionA, queue, numMessages, "A");
+ consume(sessionB, queue, numMessages, "B");
+ consume(sessionC, queue, numMessages, "C");
- // Step 10. We now consume the messages from each node. The connections must be
on different nodes
- // since if they shared nodes then the consumers would receive the messages sent
from different connections.
-
- for (int i = 0; i < numMessages; i++)
- {
- TextMessage messageA = (TextMessage)consumerA.receive(5000);
-
- System.out.println("Got message: " + messageA.getText() + "
from node A");
-
- TextMessage messageB = (TextMessage)consumerB.receive(5000);
-
- System.out.println("Got message: " + messageB.getText() + "
from node B");
-
- TextMessage messageC = (TextMessage)consumerC.receive(5000);
-
- System.out.println("Got message: " + messageC.getText() + "
from node C");
- }
-
return true;
}
finally
{
- // Step 11. Be sure to close our resources!
+ // Step 10. Be sure to close our resources!
- if (connectionA != null)
+ if (connection != null)
{
- connectionA.close();
+ connection.close();
}
- if (connectionB != null)
- {
- connectionB.close();
- }
-
- if (connectionC != null)
- {
- connectionC.close();
- }
-
if (initialContext != null)
{
initialContext.close();
}
}
}
+
+ private void consume(Session session, Queue queue, int numMessages, String node)
throws JMSException
+ {
+ MessageConsumer consumer = session.createConsumer(queue);
+ for (int i = 0; i < numMessages; i++)
+ {
+ TextMessage message = (TextMessage)consumer.receive(2000);
+ System.out.println("Got message: " + message.getText() + " from
node " + node);
+ }
+
+ System.out.println("receive other message from node " + node + ":
" + consumer.receive(2000));
+
+ }
}