149 lines
5.8 KiB
HTML
149 lines
5.8 KiB
HTML
<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> |