http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-multiple-failover/readme.html ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-multiple-failover/readme.html b/examples/broker-features/ha/replicated-multiple-failover/readme.html new file mode 100644 index 0000000..da37085 --- /dev/null +++ b/examples/broker-features/ha/replicated-multiple-failover/readme.html @@ -0,0 +1,45 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<html> + <head> + <title>ActiveMQ Artemis JMS Multiple Failover using Replication 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 Multiple Failover using Replication Example</h1> + + <pre>To run the example, simply type <b>mvn verify</b> from this directory.</pre> + + + <p>This example demonstrates three servers coupled as a live-backup-backup group for high availability (HA) using replication, and a client + connection failing over from live to backup when the live server is crashed and then to the second backup once the new live fails.</p> + + <p>For more information on ActiveMQ Artemis 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 -Pexample</code> 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> + </body> +</html>
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-multiple-failover/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedMultipleFailoverExample.java ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-multiple-failover/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedMultipleFailoverExample.java b/examples/broker-features/ha/replicated-multiple-failover/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedMultipleFailoverExample.java new file mode 100644 index 0000000..491d792 --- /dev/null +++ b/examples/broker-features/ha/replicated-multiple-failover/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedMultipleFailoverExample.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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. + */ +package org.apache.activemq.artemis.jms.example; + +import org.apache.activemq.artemis.util.ServerUtil; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; + +public class ReplicatedMultipleFailoverExample { + + private static Process server0; + + private static Process server1; + + private static Process server2; + + public static void main(final String[] args) throws Exception { + final int numMessages = 30; + + Connection connection = null; + + InitialContext initialContext = null; + + try { + server0 = ServerUtil.startServer(args[0], ReplicatedMultipleFailoverExample.class.getSimpleName() + "0", 0, 5000); + server1 = ServerUtil.startServer(args[1], ReplicatedMultipleFailoverExample.class.getSimpleName() + "1", 1, 5000); + server2 = ServerUtil.startServer(args[2], ReplicatedMultipleFailoverExample.class.getSimpleName() + "2", 2, 5000); + + Process[] processes = new Process[]{server0, server1, server2}; + + // Step 1. Get an initial context for looking up JNDI from the server #1 + initialContext = new InitialContext(); + + // Step 2. Look up the JMS resources from JNDI + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 3. Create a JMS Connection + connection = connectionFactory.createConnection(); + + // Step 4. Create a *non-transacted* JMS Session with client acknowledgement + Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + // Step 5. Start the connection to ensure delivery occurs + connection.start(); + + // Step 6. Create a JMS MessageProducer and a MessageConsumer + MessageProducer producer = session.createProducer(queue); + MessageConsumer consumer = session.createConsumer(queue); + + // Step 7. Send some messages to server #1, the live server + 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()); + } + + // Step 8. Receive and acknowledge a third of the sent messages + TextMessage message0 = null; + for (int i = 0; i < numMessages / 3; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + + // Step 9. Receive the rest third of the sent messages but *do not* acknowledge them yet + for (int i = numMessages / 3; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + + // Step 10. Crash server #0, the live server, and wait a little while to make sure + // it has really crashed + ServerUtil.killServer(server0); + Thread.sleep(5000); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = numMessages / 3; i < (numMessages / 3) * 2; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)%n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + + ServerUtil.killServer(processes[ServerUtil.getServer(connection)]); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = (numMessages / 3) * 2; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)%n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + } + finally { + // Step 13. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + + if (initialContext != null) { + initialContext.close(); + } + + ServerUtil.killServer(server0); + ServerUtil.killServer(server1); + ServerUtil.killServer(server2); + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server0/broker.xml b/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..43f1693 --- /dev/null +++ b/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,95 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <ha-policy> + <replication> + <master/> + </replication> + </ha-policy> + + <!-- Connectors --> + <connectors> + <connector name="netty-connector">tcp://localhost:61616</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor> + </acceptors> + + <broadcast-groups> + <broadcast-group name="bg-group1"> + <group-address>${udp-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>${udp-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> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server1/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server1/broker.xml b/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server1/broker.xml new file mode 100644 index 0000000..7f17fb8 --- /dev/null +++ b/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server1/broker.xml @@ -0,0 +1,95 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <ha-policy> + <replication> + <slave/> + </replication> + </ha-policy> + + <!-- Connectors --> + <connectors> + <connector name="netty-connector">tcp://localhost:61617</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61617</acceptor> + </acceptors> + + <broadcast-groups> + <broadcast-group name="bg-group1"> + <group-address>${udp-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>${udp-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> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server2/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server2/broker.xml b/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server2/broker.xml new file mode 100644 index 0000000..c5f06cc --- /dev/null +++ b/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/activemq/server2/broker.xml @@ -0,0 +1,95 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <ha-policy> + <replication> + <slave/> + </replication> + </ha-policy> + + <!-- Connectors --> + <connectors> + <connector name="netty-connector">tcp://localhost:61618</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61618</acceptor> + </acceptors> + + <broadcast-groups> + <broadcast-group name="bg-group1"> + <group-address>${udp-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>${udp-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> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/jndi.properties b/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/jndi.properties new file mode 100644 index 0000000..7f7a19f --- /dev/null +++ b/examples/broker-features/ha/replicated-multiple-failover/src/main/resources/jndi.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF 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. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1 +queue.queue/exampleQueue=exampleQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-transaction-failover/pom.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-transaction-failover/pom.xml b/examples/broker-features/ha/replicated-transaction-failover/pom.xml new file mode 100644 index 0000000..4c1839e --- /dev/null +++ b/examples/broker-features/ha/replicated-transaction-failover/pom.xml @@ -0,0 +1,104 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>broker-failover</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>replicated-transaction-failover</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Replicated Transaction Failover Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-cli</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create0</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server0</instance> + <configuration>${basedir}/target/classes/activemq/server0</configuration> + <javaOptions>-Dudp-address=${udp-address}</javaOptions> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <configuration>${basedir}/target/classes/activemq/server1</configuration> + <javaOptions>-Dudp-address=${udp-address}</javaOptions> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.ReplicatedTransactionFailoverExample + </clientClass> + <args> + <param>${basedir}/target/server0</param> + <param>${basedir}/target/server1</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>replicated-transaction-failover</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-transaction-failover/readme.html ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-transaction-failover/readme.html b/examples/broker-features/ha/replicated-transaction-failover/readme.html new file mode 100644 index 0000000..4206588 --- /dev/null +++ b/examples/broker-features/ha/replicated-transaction-failover/readme.html @@ -0,0 +1,148 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<html> + <head> + <title>ActiveMQ Artemis JMS Failover With Transaction using Replication 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 With Transaction using Replication Example</h1> + + <p>This example demonstrates two servers coupled as a live-backup pair for high availability (HA) using replication, and a client + connection failing over from live to backup when the live server is crashed.</p> + <p>Failover behavior differs whether the JMS session is transacter or not.</p> + <p>When a <em>transacted</em> JMS session is used, once-and-only once delivery is guaranteed.</p> + <ul> + <li>if the failover occurs while there is an in-flight transaction, the transaction will be flagged as <em>rollback only</em>. In that case, the JMS client + will need to retry the transaction work.</li> + <li>if the failover occurs while there is <em>no</em> in-flight transaction, the failover will be transparent to the user.</li> + </ul> + <p>ActiveMQ Artemis also provides an example for <a href="../non-transactional-failover/readme.html">non-transaction failover</a>.</p> + <p>For more information on ActiveMQ Artemis 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 -Pexample</code> 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>transacted</em> Session</li> + <pre class="prettyprint"> + Session session = connection.createSession(true, 0); + </pre> + + <li>Start the connection to ensure delivery occurs</li> + <pre class="prettyprint"> + connection.start(); + </pre> + + <li>Create a JMS MessageProducer</li> + <pre class="prettyprint"> + MessageProducer producer = session.createProducer(queue); + </pre> + + <li>Create a JMS MessageConsumer</li> + <pre class="prettyprint"> + MessageConsumer consumer = session.createConsumer(queue); + </pre> + + <li>Send half of the messages, kill the live server and send the remaining messages</li> + <pre class="prettyprint"> + sendMessages(session, producer, numMessages, true); + </pre> + + <p>When server #1 crashes, the client automatically detects the failure and automatically + fails over from server #1 to server #0 (in your real program you wouldn't need to sleep). + </p> + + <li>As failover occurred during transaction, the session has been marked for <em>rollback only</em> and commit will fail</li> + <pre class="prettyprint"> + try + { + session.commit(); + } catch (TransactionRolledBackException e) + { + System.err.println("transaction has been rolled back: " + e.getMessage()); + } + </pre> + + <li>We resend all the messages</li> + <pre class="prettyprint"> + sendMessages(session, producer, numMessages, false); + </pre> + + <li>We commit the session successfully: the messages will be all delivered to the activated backup server</li> + <pre class="prettyprint"> + session.commit(); + </pre> + + + <li>We are now transparently reconnected to server #0, the backup server. + We consume the messages sent before the crash of the live server, commit the session, and check there are no other message on the queue</li> + <pre class="prettyprint"> + for (int i = 0; i < numMessages; i++) + { + TextMessage message0 = (TextMessage)consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + session.commit(); + System.out.println("Other message on the server? " + consumer.receive(5000)); + </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> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-transaction-failover/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedTransactionFailoverExample.java ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-transaction-failover/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedTransactionFailoverExample.java b/examples/broker-features/ha/replicated-transaction-failover/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedTransactionFailoverExample.java new file mode 100644 index 0000000..e6887c7 --- /dev/null +++ b/examples/broker-features/ha/replicated-transaction-failover/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedTransactionFailoverExample.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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. + */ +package org.apache.activemq.artemis.jms.example; + +import org.apache.activemq.artemis.api.core.Message; +import org.apache.activemq.artemis.util.ServerUtil; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.jms.TransactionRolledBackException; +import javax.naming.InitialContext; + +/** + * A simple example that demonstrates failover of the JMS connection from one node to another + * when the live server crashes using a JMS <em>transacted</em> session and replication. + */ +public class ReplicatedTransactionFailoverExample { + + private static Process server0; + + private static Process server1; + + // You need to guarantee uniqueIDs when using duplicate detection + // It needs to be unique even after a restart + // as these IDs are stored on the journal for control + // We recommend some sort of UUID, but for this example the Current Time as string would be enough + private static String uniqueID = Long.toString(System.currentTimeMillis()); + + public static void main(final String[] args) throws Exception { + final int numMessages = 10; + + Connection connection = null; + + InitialContext initialContext = null; + + try { + server0 = ServerUtil.startServer(args[0], ReplicatedTransactionFailoverExample.class.getSimpleName() + "0", 0, 5000); + server1 = ServerUtil.startServer(args[1], ReplicatedTransactionFailoverExample.class.getSimpleName() + "1", 1, 5000); + + // Step 1. Get an initial context for looking up JNDI from the server #1 + initialContext = new InitialContext(); + + // Step 2. Look-up the JMS resources from JNDI + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 3. We create a JMS Connection + connection = connectionFactory.createConnection(); + + // Step 4. We create a *transacted* JMS Session + Session session = connection.createSession(true, 0); + + // Step 5. We start the connection to ensure delivery occurs + connection.start(); + + // Step 6. We create a JMS MessageProducer + MessageProducer producer = session.createProducer(queue); + + // Step 7. We create a JMS MessageConsumer + MessageConsumer consumer = session.createConsumer(queue); + + // Step 8. We send half of the messages, kill the live server and send the remaining messages + sendMessages(session, producer, numMessages, true); + + // Step 9. As failover occurred during transaction, the session has been marked for rollback only + try { + session.commit(); + } + catch (TransactionRolledBackException e) { + System.err.println("transaction has been rolled back: " + e.getMessage()); + } + + // Step 10. We resend all the messages + sendMessages(session, producer, numMessages, false); + + // Step 11. We commit the session successfully: the messages will be all delivered to the activated backup + // server + session.commit(); + + // Step 12. We are now transparently reconnected to server #0, the backup server. + // We consume the messages sent before the crash of the live server and commit the session. + for (int i = 0; i < numMessages; i++) { + TextMessage message0 = (TextMessage) consumer.receive(5000); + + if (message0 == null) { + throw new IllegalStateException("Example failed - message wasn't received"); + } + + System.out.println("Got message: " + message0.getText()); + } + + session.commit(); + + System.out.println("Other message on the server? " + consumer.receive(5000)); + } + finally { + // Step 13. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + + if (initialContext != null) { + initialContext.close(); + } + + ServerUtil.killServer(server0); + ServerUtil.killServer(server1); + } + } + + private static void sendMessages(final Session session, + final MessageProducer producer, + final int numMessages, + final boolean killServer) throws Exception { + // We send half of messages + for (int i = 0; i < numMessages / 2; i++) { + TextMessage message = session.createTextMessage("This is text message " + i); + + // We set the duplicate detection header - so the server will ignore the same message + // if sent again after failover + + message.setStringProperty(Message.HDR_DUPLICATE_DETECTION_ID.toString(), uniqueID + i); + + producer.send(message); + + System.out.println("Sent message: " + message.getText()); + } + + if (killServer) { + ServerUtil.killServer(server0); + } + + // We send the remaining half of messages + for (int i = numMessages / 2; i < numMessages; i++) { + TextMessage message = session.createTextMessage("This is text message " + i); + + // We set the duplicate detection header - so the server will ignore the same message + // if sent again after failover + + message.setStringProperty(Message.HDR_DUPLICATE_DETECTION_ID.toString(), uniqueID + i); + + producer.send(message); + + System.out.println("Sent message: " + message.getText()); + } + } + +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/activemq/server0/broker.xml b/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..f8b076a --- /dev/null +++ b/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,96 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <ha-policy> + <replication> + <master/> + </replication> + </ha-policy> + + <!-- Connectors --> + + <connectors> + <connector name="netty-connector">tcp://localhost:61616</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor> + </acceptors> + + <broadcast-groups> + <broadcast-group name="bg-group1"> + <group-address>${udp-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>${udp-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> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/activemq/server1/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/activemq/server1/broker.xml b/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/activemq/server1/broker.xml new file mode 100644 index 0000000..f64af4e --- /dev/null +++ b/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/activemq/server1/broker.xml @@ -0,0 +1,97 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <ha-policy> + <replication> + <slave/> + </replication> + </ha-policy> + + <!-- Connectors --> + + <connectors> + <connector name="netty-connector">tcp://localhost:61617</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61617</acceptor> + </acceptors> + + <broadcast-groups> + <broadcast-group name="bg-group1"> + <group-address>${udp-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>${udp-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> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/jndi.properties b/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/jndi.properties new file mode 100644 index 0000000..7f7a19f --- /dev/null +++ b/examples/broker-features/ha/replicated-transaction-failover/src/main/resources/jndi.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF 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. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1 +queue.queue/exampleQueue=exampleQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/scale-down/pom.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/scale-down/pom.xml b/examples/broker-features/ha/scale-down/pom.xml new file mode 100644 index 0000000..e722413 --- /dev/null +++ b/examples/broker-features/ha/scale-down/pom.xml @@ -0,0 +1,105 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>broker-failover</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>scale-down</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Scale Down Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-cli</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create0</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server0</instance> + <configuration>${basedir}/target/classes/activemq/server0</configuration> + <javaOptions>-Dudp-address=${udp-address}</javaOptions> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <configuration>${basedir}/target/classes/activemq/server1</configuration> + <javaOptions>-Dudp-address=${udp-address}</javaOptions> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.ScaleDownExample</clientClass> + <args> + <param>${basedir}/target/server0</param> + <param>${basedir}/target/server1</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>scale-down</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/scale-down/readme.html ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/scale-down/readme.html b/examples/broker-features/ha/scale-down/readme.html new file mode 100644 index 0000000..4786db3 --- /dev/null +++ b/examples/broker-features/ha/scale-down/readme.html @@ -0,0 +1,51 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<html> + <head> + <title>ActiveMQ Artemis JMS Scale Down 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 Colocated Failover Shared Store Example</h1> + + <pre>To run the example, simply type <b>mvn verify</b> from this directory.</pre> + + + <p>This example demonstrates how you can configure a live server to scale down messages to another live server on shutdown. + <p>This example starts 2 live servers each one with a connector configured for the other live server.</p> + <p>The second live server is killed and its messages are scaled down to the first server on shutdown.</p> + <p>The following shows how to configure the live servers to scale down to one another.</p> + <pre class="prettyprint"> + <code> + <ha-policy> + <live-only> + <scale-down> + <connectors> + <connector-ref>server0-connector</connector-ref> + </connectors> + </scale-down> + </live-only> + </ha-policy> + </code> + </pre> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/scale-down/src/main/java/org/apache/activemq/artemis/jms/example/ScaleDownExample.java ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/scale-down/src/main/java/org/apache/activemq/artemis/jms/example/ScaleDownExample.java b/examples/broker-features/ha/scale-down/src/main/java/org/apache/activemq/artemis/jms/example/ScaleDownExample.java new file mode 100644 index 0000000..3d81a38 --- /dev/null +++ b/examples/broker-features/ha/scale-down/src/main/java/org/apache/activemq/artemis/jms/example/ScaleDownExample.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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. + */ +package org.apache.activemq.artemis.jms.example; + +import org.apache.activemq.artemis.util.ServerUtil; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; +import java.util.Hashtable; + +/** + * A simple example that demonstrates a colocated server + */ +public class ScaleDownExample { + + private static Process server0; + + private static Process server1; + + public static void main(final String[] args) throws Exception { + final int numMessages = 30; + + Connection connection = null; + Connection connection1 = null; + + InitialContext initialContext = null; + InitialContext initialContext1 = null; + + try { + server0 = ServerUtil.startServer(args[0], ScaleDownExample.class.getSimpleName() + "0", 0, 5000); + server1 = ServerUtil.startServer(args[1], ScaleDownExample.class.getSimpleName() + "1", 1, 5000); + + // Step 1. Get an initial context for looking up JNDI for both servers + Hashtable<String, Object> properties = new Hashtable<String, Object>(); + properties.put("java.naming.factory.initial", "org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory"); + properties.put("connectionFactory.ConnectionFactory", "tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1"); + properties.put("queue.queue/exampleQueue", "exampleQueue"); + initialContext = new InitialContext(properties); + + properties = new Hashtable<String, Object>(); + properties.put("java.naming.factory.initial", "org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory"); + properties.put("connectionFactory.ConnectionFactory", "tcp://localhost:61617?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1"); + initialContext1 = new InitialContext(properties); + + // Step 2. Look up the JMS resources from JNDI + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + ConnectionFactory connectionFactory1 = (ConnectionFactory) initialContext1.lookup("ConnectionFactory"); + + // Step 3. Create a JMS Connections + connection = connectionFactory.createConnection(); + connection1 = connectionFactory1.createConnection(); + + // Step 4. Create a *non-transacted* JMS Session with client acknowledgement + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Step 5. Create a JMS MessageProducers + MessageProducer producer = session.createProducer(queue); + MessageProducer producer1 = session1.createProducer(queue); + + // Step 6. Send some messages to both servers + 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()); + message = session1.createTextMessage("This is another text message " + i); + producer1.send(message); + System.out.println("Sent message: " + message.getText()); + } + + // Step 7. Crash server #1 + ServerUtil.killServer(server1); + + // Step 8. start the connection ready to receive messages + connection.start(); + + // Step 9.create a consumer + MessageConsumer consumer = session.createConsumer(queue); + + // Step 10. Receive and acknowledge all of the sent messages, the backup server that is colocated with server 1 + // will have become live and is now handling messages for server 0. + TextMessage message0 = null; + for (int i = 0; i < numMessages * 2; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + } + finally { + // Step 11. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + + if (initialContext != null) { + initialContext.close(); + } + if (connection1 != null) { + connection1.close(); + } + + if (initialContext1 != null) { + initialContext1.close(); + } + + ServerUtil.killServer(server0); + ServerUtil.killServer(server1); + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/scale-down/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/scale-down/src/main/resources/activemq/server0/broker.xml b/examples/broker-features/ha/scale-down/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..559bb5a --- /dev/null +++ b/examples/broker-features/ha/scale-down/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,117 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + <!-- Connectors --> + + <connectors> + <connector name="netty-connector">tcp://localhost:61616</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor> + </acceptors> + + <!-- Clustering configuration --> + <broadcast-groups> + <broadcast-group name="my-broadcast-group"> + <group-address>${udp-address:231.7.7.7}</group-address> + <group-port>9876</group-port> + <broadcast-period>100</broadcast-period> + <connector-ref>netty-connector</connector-ref> + </broadcast-group> + </broadcast-groups> + + <discovery-groups> + <discovery-group name="my-discovery-group"> + <group-address>${udp-address:231.7.7.7}</group-address> + <group-port>9876</group-port> + <refresh-timeout>10000</refresh-timeout> + </discovery-group> + </discovery-groups> + + <cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <retry-interval>500</retry-interval> + <reconnect-attempts>5</reconnect-attempts> + <use-duplicate-detection>true</use-duplicate-detection> + <message-load-balancing>STRICT</message-load-balancing> + <max-hops>1</max-hops> + <discovery-group-ref discovery-group-name="my-discovery-group"/> + </cluster-connection> + </cluster-connections> + + <ha-policy/> + + <!-- 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-setting match="jms.queue.activemq.management"> + <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"/> + <permission type="manage" roles="guest"/> + </security-setting> + <security-setting match="jms.queue.activemq.management.*"> + <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"/> + <permission type="manage" roles="guest"/> + </security-setting> + </security-settings> + + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/scale-down/src/main/resources/activemq/server1/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/scale-down/src/main/resources/activemq/server1/broker.xml b/examples/broker-features/ha/scale-down/src/main/resources/activemq/server1/broker.xml new file mode 100644 index 0000000..6211cd3 --- /dev/null +++ b/examples/broker-features/ha/scale-down/src/main/resources/activemq/server1/broker.xml @@ -0,0 +1,108 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <!-- Connectors --> + <connectors> + <connector name="netty-connector">tcp://localhost:61617</connector> + <connector name="server0-connector">tcp://localhost:61616</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61617</acceptor> + </acceptors> + + <!-- Clustering configuration --> + <broadcast-groups> + <broadcast-group name="my-broadcast-group"> + <group-address>${udp-address:231.7.7.7}</group-address> + <group-port>9876</group-port> + <broadcast-period>100</broadcast-period> + <connector-ref>netty-connector</connector-ref> + </broadcast-group> + </broadcast-groups> + + <discovery-groups> + <discovery-group name="my-discovery-group"> + <group-address>${udp-address:231.7.7.7}</group-address> + <group-port>9876</group-port> + <refresh-timeout>10000</refresh-timeout> + </discovery-group> + </discovery-groups> + + <cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <retry-interval>500</retry-interval> + <reconnect-attempts>5</reconnect-attempts> + <use-duplicate-detection>true</use-duplicate-detection> + <message-load-balancing>STRICT</message-load-balancing> + <max-hops>1</max-hops> + <discovery-group-ref discovery-group-name="my-discovery-group"/> + </cluster-connection> + </cluster-connections> + + <!--a live server that will scale down on server shutdown--> + <ha-policy> + <live-only> + <scale-down> + <connectors> + <connector-ref>server0-connector</connector-ref> + </connectors> + </scale-down> + </live-only> + </ha-policy> + + <!-- 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> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/stop-server-failover/pom.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/stop-server-failover/pom.xml b/examples/broker-features/ha/stop-server-failover/pom.xml new file mode 100644 index 0000000..7fb647c --- /dev/null +++ b/examples/broker-features/ha/stop-server-failover/pom.xml @@ -0,0 +1,160 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>broker-failover</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>stop-server-failover</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Stop Server Failover Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create0</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <instance>${basedir}/target/server0</instance> + <sharedStore>true</sharedStore> + <slave>false</slave> + <dataFolder>../data</dataFolder> + <failoverOnShutdown>true</failoverOnShutdown> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <instance>${basedir}/target/server1</instance> + <sharedStore>true</sharedStore> + <slave>true</slave> + <dataFolder>../data</dataFolder> + <failoverOnShutdown>true</failoverOnShutdown> + </configuration> + </execution> + <execution> + <id>start0</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <spawn>true</spawn> + <location>${basedir}/target/server0</location> + <testURI>tcp://localhost:61616</testURI> + <args> + <param>run</param> + </args> + <name>server0</name> + </configuration> + </execution> + <execution> + <id>start1</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <spawn>true</spawn> + <location>${basedir}/target/server1</location> + <testURI>tcp://localhost:61617</testURI> + <args> + <param>run</param> + </args> + <name>server1</name> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.StopServerFailoverExample</clientClass> + </configuration> + </execution> + <execution> + <id>stop0</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <location>${basedir}/target/server0</location> + <args> + <param>stop</param> + </args> + </configuration> + </execution> + <execution> + <id>stop1</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <location>${basedir}/target/server1</location> + <args> + <param>stop</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>stop-server-failover</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/stop-server-failover/readme.html ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/stop-server-failover/readme.html b/examples/broker-features/ha/stop-server-failover/readme.html new file mode 100644 index 0000000..9486cd6 --- /dev/null +++ b/examples/broker-features/ha/stop-server-failover/readme.html @@ -0,0 +1,44 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF 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. +--> + +<html> + <head> + <title>ActiveMQ Artemis 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> + + <pre>To run the example, simply type <b>mvn verify</b> from this directory, <br>or <b>mvn -PnoServer verify</b> if you want to start and create the server manually.</pre> + + + <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 whether 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 ActiveMQ Artemis failover and HA, and clustering in general, please see the clustering + section of the user manual.</p> + + </body> +</html>
