2014-10-31 06:20:28 -04:00
< html >
< head >
2014-11-19 03:44:57 -05:00
< title > ActiveMQ Application-Layer Failover 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 > Application-Layer Failover Example< / h1 >
2014-11-19 03:44:57 -05:00
< p > ActiveMQ implements fully transparent < b > automatic< / b > failover of connections from a live node to a backup node which requires
2014-10-31 06:20:28 -04:00
no special coding. This is described in a different example and requires server replication.< / p >
2014-11-19 03:44:57 -05:00
< 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 >
2014-10-31 06:20:28 -04:00
< 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 >
2014-11-19 03:44:57 -05:00
< p > For more information on ActiveMQ failover and HA, 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 >
< 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 >