[jboss-cvs] JBoss Messaging SVN: r6556 - in trunk/examples/jms/symmetric-cluster: server0 and 6 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Fri Apr 24 09:43:26 EDT 2009
Author: timfox
Date: 2009-04-24 09:43:25 -0400 (Fri, 24 Apr 2009)
New Revision: 6556
Modified:
trunk/examples/jms/symmetric-cluster/
trunk/examples/jms/symmetric-cluster/readme.html
trunk/examples/jms/symmetric-cluster/server0/
trunk/examples/jms/symmetric-cluster/server1/
trunk/examples/jms/symmetric-cluster/server2/
trunk/examples/jms/symmetric-cluster/server3/
trunk/examples/jms/symmetric-cluster/server4/
trunk/examples/jms/symmetric-cluster/server5/
trunk/examples/jms/symmetric-cluster/src/org/jboss/jms/example/SymmetricClusterExample.java
Log:
finished symmetric cluster example
Property changes on: trunk/examples/jms/symmetric-cluster
___________________________________________________________________
Name: svn:ignore
+ build
logs
Modified: trunk/examples/jms/symmetric-cluster/readme.html
===================================================================
--- trunk/examples/jms/symmetric-cluster/readme.html 2009-04-24 10:48:45 UTC (rev 6555)
+++ trunk/examples/jms/symmetric-cluster/readme.html 2009-04-24 13:43:25 UTC (rev 6556)
@@ -4,17 +4,28 @@
<link rel="stylesheet" type="text/css" href="../common/common.css">
</head>
<body>
- <h1>JBoss Messaging JMS Symmetric Cluster Example</h1>
+ <h1>JBoss Messaging Symmetric Cluster Example</h1>
<br>
- <p>This example demonstrates a JMS queue deployed on two different nodes. The two nodes are configured to form a cluster.</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>both</b> consumers receive the sent messages
- in a round-robin fashion.</p>
- <p>In other words, JBoss Messaging <b>load balances</b> the sent messages across all consumers on the cluster</p>
- <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 cluster between the two nodes
- and to load balance the messages between the nodes.</p>
+ <p>This examples demonstrates a <b>symmetric cluster</b> set-up with JBoss Messaging.</p>
+ <p>JBoss Messaging has extremely flexible clustering which allows you to set-up servers in
+ many different topologies.</p>
+ <p>The most common topology that you'll perhaps be familiar with if you are used to application
+ server clustering is a <b>symmetric cluster</b>.</p>
+ <p>With a symmetric cluster, the cluster is homogenous, i.e. each node is configured the same
+ as every other node, and every node is connected to every other node in the cluster.</p>
+ <p>By connecting node in such a way, we can, from a JMS point of view, give the impression of distributed
+ JMS queues and topics.</p>
+ <p>The configuration used in this example is very similar to the configuration used by JBoss Messaging
+ when installed as a clustered profile in JBoss Application Server.</p>
+ <p>To set up JBoss Messaging to form a symmetric cluster we simply need to mark each server as <code>clustered</code>
+ and we need to define a <code>cluster-connection</code> in <code>jbm-configuration.xml</code>.</p>
+ <p>The <code>cluster-connection</code> tells the nodes what other nodes to make connections to.
+ With a <code>cluster-connection</code> 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.</p>
+ <p>Using UDP discovery makes configuration simpler since we don't have to know what nodes are
+ available at any one time.</p>
+ <p>Here's the relevant snippet from the server configuration, which tells the server to form a cluster
+ with the other nodes:</p>
<pre>
<code>
<cluster-connection name="my-cluster">
@@ -27,146 +38,254 @@
</cluster-connection>
</code>
</pre>
- <p>For more information on JBoss Messaging load balancing, and clustering in general, please see the clustering
+ <p>In this example we create a symmetric cluster of three 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).</p>
+ <p>By providing each node with a backup, we ensure that, in case of failure, the cluster will continue
+ without failure, with all connections on live failing over transparently onto the backup.</p>
+ <p>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.</p>
+ <p>During the example will will also kill each live server in turn, at different times, and verify that the sending
+ consuming of messages carries on uninterrupted, as connections transparently fail over from live to backup.</p>
+ <p>For more information on configuring JBoss Messaging clustering in general, please see the clustering
section of the user manual.</p>
<h2>Example step-by-step</h2>
<p><i>To run the example, simply type <code>ant</code> from this directory</i></p>
<br>
<ol>
- <li> Get an initial context for looking up JNDI from server 0.</li>
+ <li>We instantiate a connection factory directly, specifying the UDP address and port for discovering
+ the list of servers in the cluster.
+ We could use JNDI to look-up a connection factory, but we'd need to know the JNDI server host and port for the
+ specific server to do that, and that server might not be available at the time. By creating the
+ connection factory directly we avoid having to worry about a JNDI look-up.
+ In an app server environment you could use HA-JNDI to lookup from the clustered JNDI servers without
+ having to know about a specific one.
+ </li>
+
<pre>
<code>
- ic0 = getContext(0);
+ ConnectionFactory cf = new JBossConnectionFactory("231.7.7.7", 9876);
</code>
</pre>
- <li>Look-up the JMS Queue object from JNDI</li>
+ <li>Directly instantiate JMS Queue and Topic objects</li>
<pre>
- <code>Queue queue = (Queue)ic0.lookup("/queue/exampleQueue");</code>
+ <code>
+ Queue queue = new JBossQueue("exampleQueue");
+
+ Topic topic = new JBossTopic("exampleTopic");
+ </code>
</pre>
- <li>Look-up a JMS Connection Factory object from JNDI on server 0</li>
+ <li>We create three connections, they should be to different nodes of the cluster in a round-robin fashion
+ and start them.</li>
<pre>
- <code>ConnectionFactory cf0 = (ConnectionFactory)ic0.lookup("/ConnectionFactory");</code>
+ <code>
+ connection0 = cf.createConnection();
+
+ connection1 = cf.createConnection();
+
+ connection2 = cf.createConnection();
+
+ connection0.start();
+
+ connection1.start();
+
+ connection2.start();
+ </code>
</pre>
- <li>Get an initial context for looking up JNDI from server 1.</li>
+ <li>We create a session on each connection.</li>
<pre>
- <code>ic1 = getContext(1);</code>
+ <code>
+ Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ </code>
</pre>
- <li>Look-up a JMS Connection Factory object from JNDI on server 1</li>
+ <li>We create a topic subscriber on each server.</li>
<pre>
- <code>ConnectionFactory cf1 = (ConnectionFactory)ic1.lookup("/ConnectionFactory");
+ <code>
+ MessageConsumer subscriber0 = session0.createConsumer(topic);
+
+ MessageConsumer subscriber1 = session1.createConsumer(topic);
+
+ MessageConsumer subscriber2 = session2.createConsumer(topic);
</code>
</pre>
- <li>We create a JMS Connection connection0 which is a connection to server 0</li>
+ <li>We create a queue consumer on server 0.</li>
<pre>
<code>
- connection0 = cf0.createConnection();
+ MessageConsumer consumer0 = session0.createConsumer(queue);
</code>
</pre>
- <li>We create a JMS Connection connection1 which is a connection to server 1</li>
+ <li>We create an anonymous message producer on server 2.</li>
<pre>
<code>
- connection1 = cf1.createConnection();
+ MessageProducer producer2 = session2.createProducer(null);
</code>
</pre>
- <li>We create a JMS Session on server 0</li>
+ <li>We send 500 messages each to the queue and topic.</li>
<pre>
<code>
- Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ 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);
+ }
</code>
</pre>
- <li>We create a JMS Session on server 1</li>
+ <li>We kill live server 1, this will cause connection1 to transparently fail over onto server 4.</li>
<pre>
<code>
- Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ killServer(1);
</code>
</pre>
- <li>We start the connections to ensure delivery occurs on them</li>
+ <li>Verify all subscribers receive the messages.</li>
<pre>
<code>
- connection0.start();
-
- connection1.start();
+ 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)consumer0.receive(5000);
+
+ if (received3 == null)
+ {
+ return false;
+ }
+ }
</code>
</pre>
- <li>We create JMS MessageConsumer objects on server 0 and server 1</li>
+ <li>Send 500 more messages to the queue and topic.</li>
<pre>
<code>
- MessageConsumer consumer0 = session0.createConsumer(queue);
-
- MessageConsumer consumer1 = session1.createConsumer(queue);
+ for (int i = 0; i < numMessages; i++)
+ {
</code>
</pre>
- <li>We create a JMS MessageProducer object on server 0.</li>
+ <li>Half way through sending we kill server 2</li>
<pre>
<code>
- MessageProducer producer = session0.createProducer(queue);</code>
+ if (i == numMessages / 2)
+ {
+ killServer(2);
+ }
+
+ TextMessage message3 = session2.createTextMessage("Topic message 2");
+
+ producer2.send(topic, message3);
+
+ TextMessage message4 = session2.createTextMessage("Queue message 2");
+
+ producer2.send(queue, message4);
+ }
</pre>
- <li>We send some messages to server 0.</li>
+ <li>Verify all the messages are received by the subscribers.</li>
<pre>
<code>
- final int numMessages = 10;
-
- 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());
- }
+ for (int i = 0; i < numMessages; i++)
+ {
</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.
- JBoss Messaging has <b>load balanced</b> the messages between the available consumers on the different nodes.
- JBoss Messaging can be configured to always load balance messages to all nodes, or to only balance messages
- 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.
+ <li>Half way through receiving, we kill server 0.</li>
<pre>
<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");
- }
+ if (i == numMessages / 2)
+ {
+ killServer(0);
+ }
+
+ 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)consumer0.receive(5000);
+
+ if (received3 == null)
+ {
+ return false;
+ }
+ }
</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>
+ <li>Be sure to close our resources!</li>
<pre>
<code>
- finally
- {
- if (connection0 != null)
- {
- connection0.close();
- }
-
- if (connection1 != null)
- {
- connection1.close();
- }
- }
+ finally
+ {
+ if (connection0 != null)
+ {
+ connection0.close();
+ }
+
+ if (connection1 != null)
+ {
+ connection1.close();
+ }
+
+ if (connection2 != null)
+ {
+ connection2.close();
+ }
+ }
</code>
</pre>
Property changes on: trunk/examples/jms/symmetric-cluster/server0
___________________________________________________________________
Name: svn:ignore
+ data
logs
Property changes on: trunk/examples/jms/symmetric-cluster/server1
___________________________________________________________________
Name: svn:ignore
+ data
logs
Property changes on: trunk/examples/jms/symmetric-cluster/server2
___________________________________________________________________
Name: svn:ignore
+ data
logs
Property changes on: trunk/examples/jms/symmetric-cluster/server3
___________________________________________________________________
Name: svn:ignore
+ data
logs
Property changes on: trunk/examples/jms/symmetric-cluster/server4
___________________________________________________________________
Name: svn:ignore
+ data
logs
Property changes on: trunk/examples/jms/symmetric-cluster/server5
___________________________________________________________________
Name: svn:ignore
+ data
logs
Modified: trunk/examples/jms/symmetric-cluster/src/org/jboss/jms/example/SymmetricClusterExample.java
===================================================================
--- trunk/examples/jms/symmetric-cluster/src/org/jboss/jms/example/SymmetricClusterExample.java 2009-04-24 10:48:45 UTC (rev 6555)
+++ trunk/examples/jms/symmetric-cluster/src/org/jboss/jms/example/SymmetricClusterExample.java 2009-04-24 13:43:25 UTC (rev 6556)
@@ -131,11 +131,11 @@
// Step 7. We create an anonymous message producer on just one server 2
MessageProducer producer2 = session2.createProducer(null);
-
- final int numMessages = 500;
-
+
// Step 8. We send 500 messages each to the queue and topic
+ final int numMessages = 500;
+
for (int i = 0; i < numMessages; i++)
{
TextMessage message1 = session2.createTextMessage("Topic message 1");
@@ -151,6 +151,8 @@
killServer(1);
+ Thread.sleep(500);
+
// Step 9. Verify all subscribers receive the messages
for (int i = 0; i < numMessages; i++)
More information about the jboss-cvs-commits
mailing list