You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2017/12/19 03:26:32 UTC
[2/2] activemq-artemis git commit: [ARTEMIS-550] add section on
migrating virtual topics and test to validate
[ARTEMIS-550] add section on migrating virtual topics and test to validate
Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/a1a30fb7
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/a1a30fb7
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/a1a30fb7
Branch: refs/heads/master
Commit: a1a30fb7fda4873e4246103ec6498ba487f9e706
Parents: 2d81f2d
Author: gtully <ga...@gmail.com>
Authored: Thu Dec 14 16:30:56 2017 +0000
Committer: Clebert Suconic <cl...@apache.org>
Committed: Mon Dec 18 22:25:28 2017 -0500
----------------------------------------------------------------------
artemis-website/pom.xml | 9 ++
artemis-website/src/main/resources/index.html | 1 +
docs/migration-guide/en/SUMMARY.md | 1 +
docs/migration-guide/en/VirtualTopics.md | 40 +++++++++
.../integration/openwire/FQQNOpenWireTest.java | 94 ++++++++++++++++++++
5 files changed, 145 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/a1a30fb7/artemis-website/pom.xml
----------------------------------------------------------------------
diff --git a/artemis-website/pom.xml b/artemis-website/pom.xml
index 1f818a0..a858928 100644
--- a/artemis-website/pom.xml
+++ b/artemis-website/pom.xml
@@ -80,6 +80,7 @@
<webapp-dir>${project.artifactId}-${project.version}</webapp-dir>
<webapp-outdir-user-manual>${basedir}/target/classes/user-manual</webapp-outdir-user-manual>
<webapp-outdir-hacking-guide>${basedir}/target/classes/hacking-guide</webapp-outdir-hacking-guide>
+ <webapp-outdir-migration-guide>${basedir}/target/classes/migration-guide</webapp-outdir-migration-guide>
<frontend-maven-plugin-version>0.0.29</frontend-maven-plugin-version>
<nodeVersion>v6.11.0</nodeVersion>
@@ -191,6 +192,14 @@
<arg value="${basedir}/../docs/hacking-guide/en" />
<arg value="${webapp-outdir-hacking-guide}" />
</exec>
+ <mkdir dir="${webapp-outdir-migration-guide}" />
+ <echo>executing ${gitbook.cmd}</echo>
+ <exec executable="${gitbook.cmd}" failonerror="true">
+ <env key="PATH" path="${basedir}/node" />
+ <arg value="build" />
+ <arg value="${basedir}/../docs/migration-guide/en" />
+ <arg value="${webapp-outdir-migration-guide}" />
+ </exec>
</target>
</configuration>
<goals>
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/a1a30fb7/artemis-website/src/main/resources/index.html
----------------------------------------------------------------------
diff --git a/artemis-website/src/main/resources/index.html b/artemis-website/src/main/resources/index.html
index 25d6231..c44d9ad 100644
--- a/artemis-website/src/main/resources/index.html
+++ b/artemis-website/src/main/resources/index.html
@@ -55,6 +55,7 @@
<li><a target="_blank" href="api/index.html">API</a></li>
<li><a target="_blank" href="user-manual/index.html">User Manual</a></li>
<li><a target="_blank" href="hacking-guide/index.html">Hacking Guide</a></li>
+ <li><a target="_blank" href="migration-guide/index.html">Migration Guide</a></li>
<li><a href="examples/index.html">Examples</a></li>
<li><a href="http://activemq.apache.org/artemis/">Apache ActiveMQ Artemis Website</a></li>
</ul>
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/a1a30fb7/docs/migration-guide/en/SUMMARY.md
----------------------------------------------------------------------
diff --git a/docs/migration-guide/en/SUMMARY.md b/docs/migration-guide/en/SUMMARY.md
index 21c9eed..3c30dd3 100644
--- a/docs/migration-guide/en/SUMMARY.md
+++ b/docs/migration-guide/en/SUMMARY.md
@@ -3,6 +3,7 @@
* [Configuration](configuration.md)
* [Connectors](connectors.md)
* [Destinations](destinations.md)
+* [Virtual Topics](VirtualTopics.md)
* [Authentication](authentication.md)
* [Authorization](authorization.md)
* [SSL](ssl.md)
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/a1a30fb7/docs/migration-guide/en/VirtualTopics.md
----------------------------------------------------------------------
diff --git a/docs/migration-guide/en/VirtualTopics.md b/docs/migration-guide/en/VirtualTopics.md
new file mode 100644
index 0000000..e0775ad
--- /dev/null
+++ b/docs/migration-guide/en/VirtualTopics.md
@@ -0,0 +1,40 @@
+Virtual Topics
+==============
+
+Virtual Topics (a specialisation of virtual destinations) in ActiveMQ 5.x typically address two different but related
+problems. Lets take each in turn:
+
+Shared access to a JMS durable topic subscription
+-------------------------------------------------
+With JMS1.1, a durable subscription is identified by the pair of clientId and subscriptionName. The clientId
+component must be unique to a connection on the broker. This means that the subscription is exclusive. It is
+not possible to load balance the stream of messages across consumers and quick failover is difficult because the
+existing connection state on the broker needs to be first disposed.
+With virtual topics, each subscription's stream of messages is redirected to a queue.
+
+JMS2.0 adds the possibility of shared subscriptions with new API's that are fully supported in Artemis.
+Secondly, Artemis uses a queue per topic subscriber model internally and it is possibly to directly address the
+subscription queue using it's Fully Qualified Queue name (FQQN).
+
+For example, a default 5.x consumer for topic `VirtualTopic.Orders` subscription `A`:
+```
+ ...
+ Queue subscriptionQueue = session.createQueue("Consumer.A.VirtualTopic.Orders");
+ session.createConsumer(subscriptionQueue);
+
+```
+would be replaced with an Artemis FQQN comprised of the address and queue.
+```
+ ...
+ Queue subscriptionQueue = session.createQueue("VirtualTopic.Orders::Consumer.A");
+ session.createConsumer(subscriptionQueue);
+```
+
+Durable topic subscribers in a network of brokers
+-------------------------------------------------
+The store and forward network bridges in 5.x create a durable subscriber per destination. As demand migrates across a
+network, duplicate durable subs get created on each node in the network but they do not migrate. The end result can
+result in duplicate message storage and ultimately duplicate delivery, which is not good.
+When durable subscribers map to virtual topic subscriber queues, the queues can migrate and the problem can be avoided.
+
+In Artemis, because a durable sub is modeled as a queue, this problem does not arise.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/a1a30fb7/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/FQQNOpenWireTest.java
----------------------------------------------------------------------
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/FQQNOpenWireTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/FQQNOpenWireTest.java
index 91f4e24..ff819ec 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/FQQNOpenWireTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/FQQNOpenWireTest.java
@@ -39,7 +39,9 @@ import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.core.postoffice.Bindings;
import org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding;
import org.apache.activemq.artemis.core.server.QueueQueryResult;
+import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.utils.CompositeAddress;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -266,4 +268,96 @@ public class FQQNOpenWireTest extends OpenWireTestBase {
}
}
}
+
+ @Test
+ public void testVirtualTopicFQQN() throws Exception {
+ Connection exConn = null;
+
+ SimpleString topic = new SimpleString("VirtualTopic.Orders");
+ SimpleString subscriptionQ = new SimpleString("Consumer.A");
+
+ this.server.addAddressInfo(new AddressInfo(topic, RoutingType.MULTICAST));
+ this.server.createQueue(topic, RoutingType.MULTICAST, subscriptionQ, null, true, false, -1, false, true);
+
+ try {
+ ActiveMQConnectionFactory exFact = new ActiveMQConnectionFactory();
+ exFact.setWatchTopicAdvisories(false);
+ exConn = exFact.createConnection();
+ exConn.start();
+
+ Session session = exConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Destination destination = session.createTopic(topic.toString());
+ MessageProducer producer = session.createProducer(destination);
+
+ Destination destinationFQN = session.createQueue(CompositeAddress.toFullQN(topic, subscriptionQ).toString());
+ MessageConsumer messageConsumerA = session.createConsumer(destinationFQN);
+ MessageConsumer messageConsumerB = session.createConsumer(destinationFQN);
+
+ TextMessage message = session.createTextMessage("This is a text message");
+ producer.send(message);
+
+ // only one consumer should get the message
+ TextMessage messageReceivedA = (TextMessage) messageConsumerA.receive(2000);
+ TextMessage messageReceivedB = (TextMessage) messageConsumerB.receive(2000);
+
+ assertTrue((messageReceivedA == null || messageReceivedB == null));
+ String text = messageReceivedA != null ? messageReceivedA.getText() : messageReceivedB.getText();
+ assertEquals("This is a text message", text);
+
+ messageConsumerA.close();
+ messageConsumerB.close();
+
+ } finally {
+ if (exConn != null) {
+ exConn.close();
+ }
+ }
+ }
+
+ @Test
+ @Ignore("need to figure auto bindings creation")
+ public void testVirtualTopicFQQNAutoCreate() throws Exception {
+ Connection exConn = null;
+
+ SimpleString topic = new SimpleString("VirtualTopic.Orders");
+ SimpleString subscriptionQ = new SimpleString("Consumer.A");
+
+ this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateQueues(true);
+ this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setDefaultAddressRoutingType(RoutingType.MULTICAST);
+
+ try {
+ ActiveMQConnectionFactory exFact = new ActiveMQConnectionFactory();
+ exFact.setWatchTopicAdvisories(false);
+ exConn = exFact.createConnection();
+ exConn.start();
+
+ Session session = exConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Destination destination = session.createTopic(topic.toString());
+ MessageProducer producer = session.createProducer(destination);
+
+ Destination destinationFQN = session.createQueue(CompositeAddress.toFullQN(topic, subscriptionQ).toString());
+
+ MessageConsumer messageConsumerA = session.createConsumer(destinationFQN);
+ MessageConsumer messageConsumerB = session.createConsumer(destinationFQN);
+
+ TextMessage message = session.createTextMessage("This is a text message");
+ producer.send(message);
+
+ // only one consumer should get the message
+ TextMessage messageReceivedA = (TextMessage) messageConsumerA.receive(2000);
+ TextMessage messageReceivedB = (TextMessage) messageConsumerB.receive(2000);
+
+ assertTrue((messageReceivedA == null || messageReceivedB == null));
+ String text = messageReceivedA != null ? messageReceivedA.getText() : messageReceivedB.getText();
+ assertEquals("This is a text message", text);
+
+ messageConsumerA.close();
+ messageConsumerB.close();
+
+ } finally {
+ if (exConn != null) {
+ exConn.close();
+ }
+ }
+ }
}