http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/colocated-failover-scale-down/pom.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover-scale-down/pom.xml b/examples/broker-features/ha/colocated-failover-scale-down/pom.xml new file mode 100644 index 0000000..9213d18 --- /dev/null +++ b/examples/broker-features/ha/colocated-failover-scale-down/pom.xml @@ -0,0 +1,103 @@ +<?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>colocated-failover-scale-down</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Colocated Failover Recover Only 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> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <configuration>${basedir}/target/classes/activemq/server1</configuration> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.ColocatedFailoverScaleDownExample + </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>colocated-failover-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/colocated-failover-scale-down/readme.html ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover-scale-down/readme.html b/examples/broker-features/ha/colocated-failover-scale-down/readme.html new file mode 100644 index 0000000..8be5030 --- /dev/null +++ b/examples/broker-features/ha/colocated-failover-scale-down/readme.html @@ -0,0 +1,65 @@ +<!-- +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 Colocated Failover 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 Recover Only Example</h1> + <pre>To run the example, simply type <b>mvn verify</b> from this directory. This example will always spawn and stop multiple servers.</pre> + + + <p>This example demonstrates how you can colocate live and backup servers in the same VM. We do this by creating an + HA Policy that is colocated. colocated means that backup servers can be created and maintained by live servers on behalf + of other requesting live servers. In this example we create a colocated shared store server that will scale down. + That is it will not become live but scale down the journal to the colocated live server. + <p>This example starts 2 live servers each will request the other to create a backup.</p> + <p>The first live server will be killed and the backup in the second will recover the journal and recreate its state + in the live server it shares its VM with.</p> + <p>The following shows how to configure the backup, the slave is configured <b><scale-down/></b> which means + that the backup server will not fully start on fail over, instead it will just recover the journal and write it + to its parent live server.</p> + <pre class="prettyprint"> + <code><ha-policy> + <shared-store> + <colocated> + <backup-port-offset>100</backup-port-offset> + <backup-request-retries>-1</backup-request-retries> + <backup-request-retry-interval>2000</backup-request-retry-interval> + <max-backups>1</max-backups> + <request-backup>true</request-backup> + <master/> + <slave> + <scale-down/> + </slave> + </colocated> + </shared-store> + </ha-policy> + </code> + </pre> + <p>Notice that we dont need to specify a scale down connector as it will use most appropriate + from the list of available connectors which in this case is the first INVM connector</p> + <p> One other thing to notice is that the cluster connection has its reconnect attempts set to 5, this is so it will + disconnect instead of trying to reconnect to a backup that doesn't exist.</p> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/colocated-failover-scale-down/src/main/java/org/apache/activemq/artemis/jms/example/ColocatedFailoverScaleDownExample.java ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover-scale-down/src/main/java/org/apache/activemq/artemis/jms/example/ColocatedFailoverScaleDownExample.java b/examples/broker-features/ha/colocated-failover-scale-down/src/main/java/org/apache/activemq/artemis/jms/example/ColocatedFailoverScaleDownExample.java new file mode 100644 index 0000000..c3a87ec --- /dev/null +++ b/examples/broker-features/ha/colocated-failover-scale-down/src/main/java/org/apache/activemq/artemis/jms/example/ColocatedFailoverScaleDownExample.java @@ -0,0 +1,140 @@ +/* + * 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 server side load-balancing of messages between the queue instances on different + * nodes of the cluster. + */ +public class ColocatedFailoverScaleDownExample { + + 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], ColocatedFailoverScaleDownExample.class.getSimpleName() + "0", 0, 5000); + server1 = ServerUtil.startServer(args[1], ColocatedFailoverScaleDownExample.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:61617"); + initialContext1 = 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:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1"); + properties.put("queue.queue/exampleQueue", "exampleQueue"); + initialContext = 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.CLIENT_ACKNOWLEDGE); + Session session1 = connection1.createSession(false, Session.CLIENT_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 #0, the live server, and wait a little while to make sure + // it has really crashed + ServerUtil.killServer(server0); + System.out.println("Waiting for scale-down to complete..."); + Thread.sleep(10000); + + // Step 8. start the connection ready to receive messages + connection1.start(); + + // Step 9.create a consumer + MessageConsumer consumer = session1.createConsumer(queue); + + // Step 10. Receive and acknowledge all of the sent messages, notice that they will be out of order, this is + // because they were initially round robined to both nodes then when the server failed were reloaded into the + // live server. + TextMessage message0 = null; + for (int i = 0; i < numMessages * 2; i++) { + message0 = (TextMessage) consumer.receive(5000); + if (message0 == null) { + throw new IllegalStateException("Message not received!"); + } + 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/colocated-failover-scale-down/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover-scale-down/src/main/resources/activemq/server0/broker.xml b/examples/broker-features/ha/colocated-failover-scale-down/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..60201ca --- /dev/null +++ b/examples/broker-features/ha/colocated-failover-scale-down/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,129 @@ +<?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.dir:../data}/bindings</bindings-directory> + + <journal-directory>${data.dir:../data}/journal</journal-directory> + + <large-messages-directory>${data.dir:../data}/largemessages</large-messages-directory> + + <paging-directory>${data.dir:../data}/paging</paging-directory> + <!-- Connectors --> + + <connectors> + <connector name="invm-connector">vm://0</connector> + <connector name="netty-connector">tcp://localhost:61616</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="invm-acceptor">vm://0</acceptor> + <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> + <!-- since the backup servers scale down we need a sensible setting here so the bridge will stop --> + <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 colocated server that will allow shared store backups to be requested, the default for this template is to scale down--> + <ha-policy> + <shared-store> + <colocated> + <backup-port-offset>100</backup-port-offset> + <backup-request-retries>-1</backup-request-retries> + <backup-request-retry-interval>2000</backup-request-retry-interval> + <max-backups>1</max-backups> + <request-backup>true</request-backup> + <master> + <failover-on-shutdown>true</failover-on-shutdown> + </master> + <slave> + <scale-down/> + </slave> + </colocated> + </shared-store> + </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"/> + </security-setting> + <security-setting match="jms.queue.activemq.management"> + <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/colocated-failover-scale-down/src/main/resources/activemq/server1/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover-scale-down/src/main/resources/activemq/server1/broker.xml b/examples/broker-features/ha/colocated-failover-scale-down/src/main/resources/activemq/server1/broker.xml new file mode 100644 index 0000000..7892fc1 --- /dev/null +++ b/examples/broker-features/ha/colocated-failover-scale-down/src/main/resources/activemq/server1/broker.xml @@ -0,0 +1,127 @@ +<?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.dir:../data}/bindings</bindings-directory> + + <journal-directory>${data.dir:../data}/journal</journal-directory> + + <large-messages-directory>${data.dir:../data}/largemessages</large-messages-directory> + + <paging-directory>${data.dir:../data}/paging</paging-directory> + + <!-- Connectors --> + <connectors> + <connector name="invm-connector">vm://0</connector> + <connector name="netty-connector">tcp://localhost:61617</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="invm-acceptor">vm://0</acceptor> + <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> + <!-- since the backup servers scale down we need a sensible setting here so the bridge will stop --> + <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 colocated server that will allow shared store backups to be requested, the default for this template is to scale down--> + <ha-policy> + <shared-store> + <colocated> + <backup-port-offset>100</backup-port-offset> + <backup-request-retries>-1</backup-request-retries> + <backup-request-retry-interval>2000</backup-request-retry-interval> + <max-backups>1</max-backups> + <request-backup>true</request-backup> + <master/> + <slave> + <scale-down/> + </slave> + </colocated> + </shared-store> + </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"/> + </security-setting> + <security-setting match="jms.queue.activemq.management"> + <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/colocated-failover/pom.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover/pom.xml b/examples/broker-features/ha/colocated-failover/pom.xml new file mode 100644 index 0000000..d15a948 --- /dev/null +++ b/examples/broker-features/ha/colocated-failover/pom.xml @@ -0,0 +1,102 @@ +<?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>colocated-failover</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Colocated 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> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <configuration>${basedir}/target/classes/activemq/server1</configuration> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.ColocatedFailoverExample</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>colocated-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/colocated-failover/readme.html ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover/readme.html b/examples/broker-features/ha/colocated-failover/readme.html new file mode 100644 index 0000000..a3700d4 --- /dev/null +++ b/examples/broker-features/ha/colocated-failover/readme.html @@ -0,0 +1,56 @@ +<!-- +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 Colocated 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>JMS Colocated Failover Shared Store Example</h1> + <pre>To run the example, simply type <b>mvn verify</b> from this directory. This example will always spawn and stop multiple servers.</pre> + + <p>This example demonstrates how you can colocate live and backup servers in the same VM. We do this by creating an + HA Policy that is colocated. colocated means that backup servers can be created and maintained by live servers on behalf + of other requesting live servers. In this example we create a colocated shared store server. + <p>This example starts 2 live servers each with a backup server that backs up the other live server.</p> + <p>The first live server will be killed and the backup in the second will become live</p> + <p>The following shows how to configure the live servers to request and allow backups to be deployed</p> + <pre class="prettyprint"> + <code><ha-policy> + <shared-store> + <colocated> + <backup-port-offset>100</backup-port-offset> + <backup-request-retries>-1</backup-request-retries> + <backup-request-retry-interval>2000</backup-request-retry-interval> + <max-backups>1</max-backups> + <request-backup>true</request-backup> + <master/> + <slave/> + </colocated> + </shared-store> + </ha-policy> + </code> + </pre> + <p>notice that we have used a template to set some sensible defaults but overridden the backup strategy so back ups + are full servers</p> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/colocated-failover/src/main/java/org/apache/activemq/artemis/jms/example/ColocatedFailoverExample.java ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover/src/main/java/org/apache/activemq/artemis/jms/example/ColocatedFailoverExample.java b/examples/broker-features/ha/colocated-failover/src/main/java/org/apache/activemq/artemis/jms/example/ColocatedFailoverExample.java new file mode 100644 index 0000000..3e0d07e --- /dev/null +++ b/examples/broker-features/ha/colocated-failover/src/main/java/org/apache/activemq/artemis/jms/example/ColocatedFailoverExample.java @@ -0,0 +1,147 @@ +/* + * 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 ColocatedFailoverExample { + + 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], ColocatedFailoverExample.class.getSimpleName() + "0", 0, 5000); + server1 = ServerUtil.startServer(args[1], ColocatedFailoverExample.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"); + 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 #0, the live server, and wait a little while to make sure + // it has really crashed + ServerUtil.killServer(server0); + Thread.sleep(10000); + + // Step 8. start the connection ready to receive messages + connection.start(); + connection1.start(); + + // Step 9.create a consumer + MessageConsumer consumer = session1.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; i++) { + message0 = (TextMessage) consumer.receive(5000); + if (message0 == null) { + throw new IllegalStateException("Message not received!"); + } + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + + MessageConsumer consumer1 = session.createConsumer(queue); + + // Step 11. Receive and acknowledge the rest of the sent messages from server 1. + for (int i = 0; i < numMessages; i++) { + message0 = (TextMessage) consumer1.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/colocated-failover/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover/src/main/resources/activemq/server0/broker.xml b/examples/broker-features/ha/colocated-failover/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..0a4103f --- /dev/null +++ b/examples/broker-features/ha/colocated-failover/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,115 @@ +<?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.dir:../data}/bindings</bindings-directory> + + <journal-directory>${data.dir:../data}/journal</journal-directory> + + <large-messages-directory>${data.dir:../data}/largemessages</large-messages-directory> + + <paging-directory>${data.dir:../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> + <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 colocated server that will allow shared store full backups to be requested--> + <ha-policy> + <shared-store> + <colocated> + <backup-port-offset>100</backup-port-offset> + <backup-request-retries>-1</backup-request-retries> + <backup-request-retry-interval>2000</backup-request-retry-interval> + <max-backups>1</max-backups> + <request-backup>true</request-backup> + <master> + <failover-on-shutdown>true</failover-on-shutdown> + </master> + <slave> + <failover-on-shutdown>true</failover-on-shutdown> + </slave> + </colocated> + </shared-store> + </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/colocated-failover/src/main/resources/activemq/server1/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/colocated-failover/src/main/resources/activemq/server1/broker.xml b/examples/broker-features/ha/colocated-failover/src/main/resources/activemq/server1/broker.xml new file mode 100644 index 0000000..8083f27 --- /dev/null +++ b/examples/broker-features/ha/colocated-failover/src/main/resources/activemq/server1/broker.xml @@ -0,0 +1,114 @@ +<?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.dir:../data}/bindings</bindings-directory> + + <journal-directory>${data.dir:../data}/journal</journal-directory> + + <large-messages-directory>${data.dir:../data}/largemessages</large-messages-directory> + + <paging-directory>${data.dir:../data}/paging</paging-directory> + + <!-- Connectors --> + <connectors> + <connector name="netty-connector">tcp://localhost:61617</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> + <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 colocated server that will allow shared store full backups to be requested--> + <ha-policy> + <shared-store> + <colocated> + <backup-port-offset>100</backup-port-offset> + <backup-request-retries>-1</backup-request-retries> + <backup-request-retry-interval>2000</backup-request-retry-interval> + <max-backups>1</max-backups> + <request-backup>true</request-backup> + <master> + <failover-on-shutdown>true</failover-on-shutdown> + </master> + <slave> + <failover-on-shutdown>true</failover-on-shutdown> + </slave> + </colocated> + </shared-store> + </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/ha-policy-autobackup/pom.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/ha-policy-autobackup/pom.xml b/examples/broker-features/ha/ha-policy-autobackup/pom.xml new file mode 100644 index 0000000..9322e2a --- /dev/null +++ b/examples/broker-features/ha/ha-policy-autobackup/pom.xml @@ -0,0 +1,103 @@ +<?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>ha-policy-autobackup</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS HA Policy Auto backup 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>create</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server0</instance> + <configuration>${basedir}/target/classes/activemq/server0</configuration> + </configuration> + </execution> + <execution> + <id>create2</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <configuration>${basedir}/target/classes/activemq/server1</configuration> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.HAPolicyAutoBackupExample</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>ha-policy-autobackup</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/ha-policy-autobackup/src/main/java/org/apache/activemq/artemis/jms/example/HAPolicyAutoBackupExample.java ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/ha-policy-autobackup/src/main/java/org/apache/activemq/artemis/jms/example/HAPolicyAutoBackupExample.java b/examples/broker-features/ha/ha-policy-autobackup/src/main/java/org/apache/activemq/artemis/jms/example/HAPolicyAutoBackupExample.java new file mode 100644 index 0000000..0df8bfd --- /dev/null +++ b/examples/broker-features/ha/ha-policy-autobackup/src/main/java/org/apache/activemq/artemis/jms/example/HAPolicyAutoBackupExample.java @@ -0,0 +1,155 @@ +/* + * 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 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 java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.activemq.artemis.api.core.TransportConfiguration; +import org.apache.activemq.artemis.api.core.client.ClusterTopologyListener; +import org.apache.activemq.artemis.api.core.client.TopologyMember; +import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; +import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; +import org.apache.activemq.artemis.util.ServerUtil; + +/** + * A simple example that demonstrates server side load-balancing of messages between the queue instances on different + * nodes of the cluster. + */ +public class HAPolicyAutoBackupExample { + + private static Process server0; + + private static Process server1; + + public static void main(final String[] args) throws Exception { + Connection connection0 = null; + + Connection connection1 = null; + + try { + server0 = ServerUtil.startServer(args[0], HAPolicyAutoBackupExample.class.getSimpleName() + "0", 0, 5000); + server1 = ServerUtil.startServer(args[1], HAPolicyAutoBackupExample.class.getSimpleName() + "1", 1, 5000); + + // Step 2. Look-up the JMS Queue object from JNDI + Queue queue = ActiveMQJMSClient.createQueue("exampleQueue"); + + // Step 3. new connection factories towards server 0 and 1 + ConnectionFactory cf0 = new ActiveMQConnectionFactory("tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1"); + ConnectionFactory cf1 = new ActiveMQConnectionFactory("tcp://localhost:61617?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1"); + + // Step 6. We create JMS Connections to server 0 and 1 + connection0 = cf0.createConnection(); + connection1 = cf1.createConnection(); + + // step 7. wait for the backups to start replication + waitForBackups(cf0, 2); + + // Step 8. We create JMS Sessions on server 0 and 1 + Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Step 9. We start the connections to ensure delivery occurs on them + connection0.start(); + connection1.start(); + + // Step 10. We create JMS MessageConsumer objects on server 0 and server 1 + MessageConsumer consumer0 = session0.createConsumer(queue); + MessageConsumer consumer1 = session1.createConsumer(queue); + + // Step 11. We create a JMS MessageProducer object on server 0 + MessageProducer producer = session0.createProducer(queue); + + // Step 12. We send some messages to server 0 + + final int numMessages = 10; + + for (int i = 0; i < numMessages; i++) { + TextMessage message = session0.createTextMessage("This is text message " + i); + + producer.send(message); + + System.out.println("Sent message: " + message.getText()); + } + + // Step 13. We now consume half the messages on consumer0 + // note that the other half of the messages will have been sent to server1 for consumer1 + for (int i = 0; i < numMessages / 2; i++) { + TextMessage message0 = (TextMessage) consumer0.receive(5000); + + System.out.println("Got message: " + message0.getText() + " from node 0"); + } + + // Step 14.close the consumer so it doesnt get any messages + consumer1.close(); + + // Step 15.now kill server1, messages will be scaled down to server0 + ServerUtil.killServer(server1); + Thread.sleep(5000); + + // Step 16. we now receive the messages that were on server1 but were scaled down to server0 + for (int i = 0; i < numMessages / 2; i++) { + TextMessage message0 = (TextMessage) consumer0.receive(5000); + + System.out.println("Got message: " + message0.getText() + " from node 1"); + } + } + finally { + // Step 17. Be sure to close our resources! + + if (connection0 != null) { + connection0.close(); + } + + if (connection1 != null) { + connection1.close(); + } + + ServerUtil.killServer(server0); + ServerUtil.killServer(server1); + } + } + + private static void waitForBackups(ConnectionFactory cf0, int backups) throws InterruptedException { + final CountDownLatch latch = new CountDownLatch(backups); + ((ActiveMQConnectionFactory) cf0).getServerLocator().addClusterTopologyListener(new ClusterTopologyListener() { + List<TransportConfiguration> backups = new ArrayList<TransportConfiguration>(); + + @Override + public void nodeUP(TopologyMember member, boolean last) { + if (member.getBackup() != null && !backups.contains(member.getBackup())) { + backups.add(member.getBackup()); + latch.countDown(); + } + } + + @Override + public void nodeDown(long eventUID, String nodeID) { + } + }); + latch.await(30000, TimeUnit.MILLISECONDS); + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/ha-policy-autobackup/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/ha-policy-autobackup/src/main/resources/activemq/server0/broker.xml b/examples/broker-features/ha/ha-policy-autobackup/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..db98aa0 --- /dev/null +++ b/examples/broker-features/ha/ha-policy-autobackup/src/main/resources/activemq/server0/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.dir}/server0/data/messaging/bindings</bindings-directory> + + <journal-directory>${data.dir}/server0/data/messaging/journal</journal-directory> + + <large-messages-directory>${data.dir}/server0/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${data.dir}/server0/data/messaging/paging</paging-directory> + <!-- Connectors --> + + <connectors> + <connector name="invm-connector">vm://0</connector> + <connector name="netty-connector">tcp://localhost:61616</connector> + <!-- connector to the server1 --> + <connector name="server1-connector">tcp://localhost:61617</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="invm-acceptor">vm://0</acceptor> + <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor> + </acceptors> + + <!-- HA configuration --> + <ha-policy> + <replication> + <colocated> + <max-backups>1</max-backups> + <request-backup>true</request-backup> + <backup-request-retry-interval>1000</backup-request-retry-interval> + <excludes> + <connector-ref>invm-connector</connector-ref> + <connector-ref>server1-connector</connector-ref> + <connector-ref>netty-connector</connector-ref> + </excludes> + <master/> + <slave> + <scale-down> + <connectors> + <connector-ref>invm-connector</connector-ref> + </connectors> + </scale-down> + </slave> + </colocated> + </replication> + </ha-policy> + + <cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <retry-interval>500</retry-interval> + <use-duplicate-detection>true</use-duplicate-detection> + <message-load-balancing>STRICT</message-load-balancing> + <max-hops>1</max-hops> + <static-connectors> + <connector-ref>server1-connector</connector-ref> + </static-connectors> + </cluster-connection> + </cluster-connections> + + <!-- Other config --> + + <security-settings> + <!--security for example queue--> + <security-setting match="#"> + <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/ha-policy-autobackup/src/main/resources/activemq/server1/broker.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/ha-policy-autobackup/src/main/resources/activemq/server1/broker.xml b/examples/broker-features/ha/ha-policy-autobackup/src/main/resources/activemq/server1/broker.xml new file mode 100644 index 0000000..760ce0d --- /dev/null +++ b/examples/broker-features/ha/ha-policy-autobackup/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.dir}/server0/data/messaging/bindings</bindings-directory> + + <journal-directory>${data.dir}/server0/data/messaging/journal</journal-directory> + + <large-messages-directory>${data.dir}/server0/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${data.dir}/server0/data/messaging/paging</paging-directory> + + <!-- Connectors --> + <connectors> + <connector name="invm-connector">vm://0</connector> + <connector name="netty-connector">tcp://localhost:61617</connector> + <!-- connector to the server0 --> + <connector name="server0-connector">tcp://localhost:61616</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="invm-acceptor">vm://0</acceptor> + <acceptor name="netty-acceptor">tcp://localhost:61617</acceptor> + </acceptors> + + <!-- HA configuration --> + <ha-policy> + <replication> + <colocated> + <max-backups>1</max-backups> + <request-backup>true</request-backup> + <backup-request-retry-interval>1000</backup-request-retry-interval> + <excludes> + <connector-ref>invm-connector</connector-ref> + <connector-ref>server0-connector</connector-ref> + <connector-ref>netty-connector</connector-ref> + </excludes> + <master/> + <slave> + <scale-down> + <connectors> + <connector-ref>invm-connector</connector-ref> + </connectors> + </scale-down> + </slave> + </colocated> + </replication> + </ha-policy> + + <cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <retry-interval>500</retry-interval> + <use-duplicate-detection>true</use-duplicate-detection> + <message-load-balancing>STRICT</message-load-balancing> + <max-hops>1</max-hops> + <static-connectors> + <connector-ref>server0-connector</connector-ref> + </static-connectors> + </cluster-connection> + </cluster-connections> + + <!-- Other config --> + + <security-settings> + <!--security for example queue--> + <security-setting match="#"> + <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/multiple-failover-failback/pom.xml ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/multiple-failover-failback/pom.xml b/examples/broker-features/ha/multiple-failover-failback/pom.xml new file mode 100644 index 0000000..fd04228 --- /dev/null +++ b/examples/broker-features/ha/multiple-failover-failback/pom.xml @@ -0,0 +1,121 @@ +<?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>multiple-failover-failback</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Multiple Failover Failback 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.geronimo.specs</groupId> + <artifactId>geronimo-jms_2.0_spec</artifactId> + </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> + <sharedStore>true</sharedStore> + <slave>false</slave> + <dataFolder>../data</dataFolder> + <failoverOnShutdown>true</failoverOnShutdown> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <sharedStore>true</sharedStore> + <slave>true</slave> + <dataFolder>../data</dataFolder> + <failoverOnShutdown>true</failoverOnShutdown> + </configuration> + </execution> + <execution> + <id>create2</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server2</instance> + <sharedStore>true</sharedStore> + <slave>true</slave> + <dataFolder>../data</dataFolder> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.MultipleFailoverFailbackExample</clientClass> + <args> + <param>${basedir}/target/server0</param> + <param>${basedir}/target/server1</param> + <param>${basedir}/target/server2</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>multiple-failover-failback</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/multiple-failover-failback/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverFailbackExample.java ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/multiple-failover-failback/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverFailbackExample.java b/examples/broker-features/ha/multiple-failover-failback/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverFailbackExample.java new file mode 100644 index 0000000..ab0baec --- /dev/null +++ b/examples/broker-features/ha/multiple-failover-failback/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverFailbackExample.java @@ -0,0 +1,142 @@ +/* + * 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 MultipleFailoverFailbackExample { + + public static void main(final String[] args) throws Exception { + final int numMessages = 30; + + Connection connection = null; + + InitialContext initialContext = null; + + Process[] servers = new Process[3]; + + try { + for (int i = 0; i < args.length; i++) { + servers[i] = ServerUtil.startServer(args[i], MultipleFailoverFailbackExample.class.getSimpleName() + i, i, 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. 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 #1, the live server, and wait a little while to make sure + // it has really crashed + ServerUtil.killServer(servers[0]); + + // 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(); + + servers[0] = ServerUtil.startServer(args[0], MultipleFailoverFailbackExample.class.getSimpleName() + 0, 0, 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) * 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(); + } + + for (int i = 0; i < args.length; i++) { + ServerUtil.killServer(servers[i]); + } + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/21bf4406/examples/broker-features/ha/multiple-failover-failback/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/broker-features/ha/multiple-failover-failback/src/main/resources/jndi.properties b/examples/broker-features/ha/multiple-failover-failback/src/main/resources/jndi.properties new file mode 100644 index 0000000..7f7a19f --- /dev/null +++ b/examples/broker-features/ha/multiple-failover-failback/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
