Skip to content

Commit

Permalink
added failover demonstrating forcing failover
Browse files Browse the repository at this point in the history
  • Loading branch information
andytaylor committed Dec 8, 2010
1 parent 8370cf0 commit 032e711
Show file tree
Hide file tree
Showing 15 changed files with 706 additions and 0 deletions.
13 changes: 13 additions & 0 deletions examples/jms/stop-server-failover/build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@echo off

set "OVERRIDE_ANT_HOME=..\..\..\tools\ant"

if exist "..\..\..\src\bin\build.bat" (
rem running from TRUNK
call ..\..\..\src\bin\build.bat %*
) else (
rem running from the distro
call ..\..\..\bin\build.bat %*
)

set "OVERRIDE_ANT_HOME="
15 changes: 15 additions & 0 deletions examples/jms/stop-server-failover/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh

OVERRIDE_ANT_HOME=../../../tools/ant
export OVERRIDE_ANT_HOME

if [ -f "../../../src/bin/build.sh" ]; then
# running from TRUNK
../../../src/bin/build.sh "$@"
else
# running from the distro
../../../bin/build.sh "$@"
fi



41 changes: 41 additions & 0 deletions examples/jms/stop-server-failover/build.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2009 Red Hat, Inc.
~ Red Hat licenses this file to you under the Apache License, version
~ 2.0 (the "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~ http://www.apache.org/licenses/LICENSE-2.0
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
~ implied. See the License for the specific language governing
~ permissions and limitations under the License.
-->

<!DOCTYPE project [
<!ENTITY libraries SYSTEM "../../../thirdparty/libraries.ent">
]>

<project default="run" name="HornetQ JMS Non-transaction Failover Example">

<import file="../../common/build.xml"/>

<target name="run" depends="delete-files">
<antcall target="runExample">
<param name="example.classname" value="org.hornetq.jms.example.StopServerFailoverExample"/>
<param name="hornetq.example.beans.file" value="server0 server1"/>
</antcall>
</target>

<target name="runRemote" depends="delete-files">
<antcall target="runExample">
<param name="example.classname" value="org.hornetq.jms.example.StopServerFailoverExample"/>
<param name="hornetq.example.runServer" value="false"/>
</antcall>
</target>

<target name="delete-files" depends="clean">
<delete file="./server0/KILL_ME"/>
</target>

</project>
136 changes: 136 additions & 0 deletions examples/jms/stop-server-failover/readme.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<html>
<head>
<title>HornetQ JMS Failover Without Transactions 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>JMS Failover Without Transactions Example</h1>

<p>This example demonstrates two servers coupled as a live-backup pair for high availability (HA), and a client
connection failing over from live to backup when the live server is crashed.</p>
<p>Failover behavior differs wether the JMS session is transacted or not.</p>
<p>When a <em>non-transacted</em> JMS session is used, once and only once delivery is not guaranteed
and it is possible some messages will be lost or delivered twice, depending when the failover to the backup server occurs.</p>
<p>It is up to the client to deal with such cases. To ensure once and only once delivery, the client must
use transacted JMS sessions (as shown in the example for <a href="../transaction-failover/readme.html">failover with transactions</a>).</p>
<p>For more information on HornetQ 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>./build.sh</code> (or <code>build.bat</code> on windows) from this directory</i></p>
<p>In this example, the live server is server 1, and the backup server is server 0</p>
<p>The connection will initially be created to server1, server 1 will crash, and the client will carry on
seamlessly on server 0, the backup server.</p>
<ol>
<li>Get an initial context for looking up JNDI from server #1.</li>
<pre class="prettyprint">
initialContext = getContext(1);
</pre>

<li>Look up the JMS resources from JNDI on server #1.</li>
<pre class="prettyprint">
Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
</pre>

<li>Create a JMS Connection</li>
<pre class="prettyprint">
connection = connectionFactory.createConnection();
</pre>

<li>Create a JMS <em>non-transacted</em> Session with client acknowledgement</li>
<pre class="prettyprint">
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
</pre>

<li>Start the connection to ensure delivery occurs</li>
<pre class="prettyprint">
connection.start();
</pre>

<li>Create a JMS MessageProducer and MessageConsumer</li>
<pre class="prettyprint">
MessageProducer producer = session.createProducer(queue);
MessageConsumer consumer = session.createConsumer(queue);
</pre>

<li>Send some messages to server #1</li>
<pre class="prettyprint">
for (int i = 0; i &lt; numMessages; i++)
{
TextMessage message = session.createTextMessage("This is text message " + i);
producer.send(message);
System.out.println("Sent message: " + message.getText());
}
</pre>

<li>Receive and acknowledge half of the sent messages</li>
<pre class="prettyprint">
TextMessage message0 = null;
for (int i = 0; i &lt; numMessages / 2; i++)
{
message0 = (TextMessage)consumer.receive(5000);
System.out.println("Got message: " + message0.getText());
}
message0.acknowledge();
</pre>

<li>Receive the second half of the sent messages but <em>do not acknowledge them yet</em></li>
<pre class="prettyprint">
for (int i = numMessages / 2; i &lt; numMessages; i++)
{
message0 = (TextMessage)consumer.receive(5000);
System.out.println("Got message: " + message0.getText());
}
</pre>

<li>Crash server #1, the live server, and wait a little while to make sure it has really crashed.</li>
<pre class="prettyprint">
killServer(1);
Thread.sleep(2000);
</pre>

<li>Acknowledging the second half of the sent messages will fail as failover to the backup server has occured</li>
<pre class="prettyprint">
try
{
message0.acknowledge();
}
catch (JMSException e)
{
System.err.println("Got exception while acknowledging message: " + e.getMessage());
}
</pre>

<li>Consume again the second half of the messages againg. Note that they are not considered as redelivered</li>
<pre class="prettyprint">
for (int i = numMessages / 2; i &lt; numMessages; i++)
{
message0 = (TextMessage)consumer.receive(5000);
System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered());
}
message0.acknowledge();
</pre>

<li>And finally, <strong>always</strong> 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">
finally
{
if (connection != null)
{
connection.close();
}

if (initialContext != null)
{
initialContext.close();
}
}
</pre>

</ol>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
72 changes: 72 additions & 0 deletions examples/jms/stop-server-failover/server0/hornetq-beans.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
~ Copyright 2009 Red Hat, Inc.
~ Red Hat licenses this file to you under the Apache License, version
~ 2.0 (the "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~ http://www.apache.org/licenses/LICENSE-2.0
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
~ implied. See the License for the specific language governing
~ permissions and limitations under the License.
-->

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="Naming" class="org.jnp.server.NamingBeanImpl"/>

<!-- JNDI server. Disable this if you don't want JNDI -->
<bean name="JNDIServer" class="org.jnp.server.Main">
<property name="namingInfo">
<inject bean="Naming"/>
</property>
<property name="port">1099</property>
<property name="bindAddress">localhost</property>
<property name="rmiPort">1098</property>
<property name="rmiBindAddress">localhost</property>
</bean>

<!-- MBean server -->
<bean name="MBeanServer" class="javax.management.MBeanServer">
<constructor factoryClass="java.lang.management.ManagementFactory"
factoryMethod="getPlatformMBeanServer"/>
</bean>

<!-- The core configuration -->
<bean name="Configuration" class="org.hornetq.core.config.impl.FileConfiguration"/>

<!-- The security manager -->
<bean name="HornetQSecurityManager" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl">
<start ignored="true"/>
<stop ignored="true"/>
</bean>

<!-- The core server -->
<bean name="HornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl">
<constructor>
<parameter>
<inject bean="Configuration"/>
</parameter>
<parameter>
<inject bean="MBeanServer"/>
</parameter>
<parameter>
<inject bean="HornetQSecurityManager"/>
</parameter>
</constructor>
<start ignored="true"/>
<stop ignored="true"/>
</bean>

<!-- The JMS server -->
<bean name="JMSServerManager" class="org.hornetq.jms.server.impl.JMSServerManagerImpl">
<constructor>
<parameter>
<inject bean="HornetQServer"/>
</parameter>
</constructor>
</bean>

</deployment>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<configuration xmlns="urn:hornetq"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd">

<clustered>true</clustered>

<!--we kill the server process so don't need this set to true-->
<failover-on-shutdown>false</failover-on-shutdown>

<shared-store>true</shared-store>

<!-- Connectors -->

<connectors>
<connector name="netty-connector">
<factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
<param key="port" value="5445"/>
</connector>
</connectors>

<!-- Acceptors -->
<acceptors>
<acceptor name="netty-acceptor">
<factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="port" value="5445"/>
</acceptor>
</acceptors>

<broadcast-groups>
<broadcast-group name="bg-group1">
<group-address>231.7.7.7</group-address>
<group-port>9876</group-port>
<broadcast-period>1000</broadcast-period>
<connector-ref>netty-connector</connector-ref>
</broadcast-group>
</broadcast-groups>

<discovery-groups>
<discovery-group name="dg-group1">
<group-address>231.7.7.7</group-address>
<group-port>9876</group-port>
<refresh-timeout>60000</refresh-timeout>
</discovery-group>
</discovery-groups>

<cluster-connections>
<cluster-connection name="my-cluster">
<address>jms</address>
<connector-ref>netty-connector</connector-ref>
<discovery-group-ref discovery-group-name="dg-group1"/>
</cluster-connection>
</cluster-connections>
<!-- Other config -->

<security-settings>
<!--security for example queue-->
<security-setting match="jms.queue.exampleQueue">
<permission type="createDurableQueue" roles="guest"/>
<permission type="deleteDurableQueue" roles="guest"/>
<permission type="createNonDurableQueue" roles="guest"/>
<permission type="deleteNonDurableQueue" roles="guest"/>
<permission type="consume" roles="guest"/>
<permission type="send" roles="guest"/>
</security-setting>
</security-settings>

</configuration>
32 changes: 32 additions & 0 deletions examples/jms/stop-server-failover/server0/hornetq-jms.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<configuration xmlns="urn:hornetq"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">
<!--the connection factory used by the example-->
<connection-factory name="ConnectionFactory">
<connectors>
<connector-ref connector-name="netty-connector"/>
</connectors>

<entries>
<entry name="ConnectionFactory"/>
</entries>

<ha>true</ha>
<!-- Pause 1 second between connect attempts -->
<retry-interval>1000</retry-interval>

<!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to
implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect
pause is the same length -->
<retry-interval-multiplier>1.0</retry-interval-multiplier>

<!-- Try reconnecting an unlimited number of times (-1 means "unlimited") -->
<reconnect-attempts>-1</reconnect-attempts>
</connection-factory>

<!--the queue used by the example-->
<queue name="exampleQueue">
<entry name="/queue/exampleQueue"/>
</queue>

</configuration>
7 changes: 7 additions & 0 deletions examples/jms/stop-server-failover/server0/hornetq-users.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd">
<!-- the default user. this is used where username is null-->
<defaultuser name="guest" password="guest">
<role name="guest"/>
</defaultuser>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:2099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Loading

0 comments on commit 032e711

Please sign in to comment.