mirror of
https://github.com/apache/activemq-artemis.git
synced 2025-03-06 01:10:14 +00:00
<html> <head> <title>ActiveMQ Application-Layer Failover Example</title> <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>Application-Layer Failover Example</h1> <p>ActiveMQ implements fully transparent <b>automatic</b> failover of connections from a live node to a backup node which requires no special coding. This is described in a different example and requires server replication.</p> <p>However, ActiveMQ also supports <b>Application-Layer</b> failover which is useful in the case where replication is not enabled.</p> <p>With Application-Layer failover, it's up to the application to register a JMS ExceptionListener with ActiveMQ. This listener will then be called by ActiveMQ in the event that connection failure is detected.</p> <p>User code in the ExceptionListener can then recreate any JMS Connection, Session, etc on another node and the application can continue.</p> <p>Application-Layer failover is an alternative approach to High Availabilty (HA).</p> <p>Application-Layer failover differs from automatic failover in that some client side coding is required in order to implement this. Also, with Application-Layer failover, since the old Session object dies and a new is created, any uncommitted work in the old Session will be lost, and any unacknowledged messages might be redelivered.</p> <p>For more information on ActiveMQ failover and HA, and 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>mvn verify</code> from this directory</i></p> <p>In this example, the live server is server 1, which will failover onto server 0.</p> <p>The connection will initially be created to server1, server 1 will crash, and the client will carry on on server 0, the new server. With Application-Layer failover the node that is failed over onto, does not need to be specially configured as a backup server, it can be any node.</p> <ol> <li> We create our JMS Connection, Session, MessageProducer and MessageConsumer on server 1</li> <pre class="prettyprint"> <code>createJMSObjects(1);</code> </pre> <li>We set a JMS ExceptionListener on the connection. On failure this will be called and the connection, session, etc. will be manually recreated on the backup node.</li> <pre class="prettyprint"> <code>connection.setExceptionListener(new ExampleListener());</code> </pre> <li>We send some messages to server 1, the live server.</li> <pre class="prettyprint"> <code> final int numMessages = 10; for (int i = 0; i < numMessages; i++) { TextMessage message = session.createTextMessage("This is text message " + i); producer.send(message); System.out.println("Sent message: " + message.getText()); } </code> </pre> <li>We consume those messages on server 1.</li> <pre class="prettyprint"> <code> for (int i = 0; i < numMessages; i++) { TextMessage message0 = (TextMessage)consumer.receive(5000); System.out.println("Got message: " + message0.getText()); } </code> </pre> <li>We now cause server 1, the live server to crash. After a little while the connection's ExceptionListener will register the failure and reconnection will occur.</li> <pre class="prettyprint"> <code>killServer(1);</code> </pre> <li>The connection's ExceptionListener gets called, and we lookup the JMS objects and recreate the connection, session, etc on the other node 0.</li> <pre class="prettyprint"> <code> private class ExampleListener implements ExceptionListener { public void onException(JMSException exception) { try { // Close the old resources closeResources(); // Create new JMS objects on the backup server createJMSObjects(0); failoverLatch.countDown(); } catch (Exception e) { System.err.println("Failed to handle failover"); e.printStackTrace(); } } } </code> </pre> <li>We are now connected to the other node. We now send some more messages.</li> <pre class="prettyprint"> <code> for (int i = numMessages; i < numMessages * 2; i++) { TextMessage message = session.createTextMessage("This is text message " + i); producer.send(message); System.out.println("Sent message: " + message.getText()); } </code> </pre> <li>And consume them.</li> <pre class="prettyprint"> <code> for (int i = 0; i < numMessages; i++) { TextMessage message0 = (TextMessage)consumer.receive(5000); System.out.println("Got message: " + message0.getText()); } </code> </pre> <li>And finally (no pun intended), <b>always</b> remember to close your 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 { closeResources(); } </code> </pre> </ol> </body> </html>