http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/thread-pooling.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/thread-pooling.xml b/docs/user-manual/en/thread-pooling.xml deleted file mode 100644 index 85a3189..0000000 --- a/docs/user-manual/en/thread-pooling.xml +++ /dev/null @@ -1,150 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ============================================================================= --> -<!-- 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. --> -<!-- ============================================================================= --> - -<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ -<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent"> -%BOOK_ENTITIES; -]> -<chapter id="thread-pooling"> - <title>Thread management</title> - <para>This chapter describes how ActiveMQ uses and pools threads and how you can manage - them.</para> - <para>First we'll discuss how threads are managed and used on the server side, then we'll look - at the client side.</para> - <section> - <title>Server-Side Thread Management</title> - <para>Each ActiveMQ Server maintains a single thread pool for general use, and a scheduled - thread pool for scheduled use. A Java scheduled thread pool cannot be configured to use - a standard thread pool, otherwise we could use a single thread pool for both scheduled - and non scheduled activity.</para> - <para>A separate thread pool is also used to service connections. ActiveMQ can use "old" - (blocking) IO or "new" (non-blocking) IO also called NIO. Both of these options use - a separate thread pool, but each of them behaves uniquely.</para> - <para>Since old IO requires a thread per connection its thread pool is unbounded. The thread - pool is created via <literal> - java.util.concurrent.Executors.newCachedThreadPool(ThreadFactory)</literal>. As the - JavaDoc for this method states: - <quote>Creates a thread pool that creates new threads as needed, but will reuse previously - constructed threads when they are available, and uses the provided ThreadFactory to create - new threads when needed.</quote> - Threads from this pool which are idle for more than 60 seconds will time out and be - removed. If old IO connections were serviced from the standard pool the pool would - easily get exhausted if too many connections were made, resulting in the server "hanging" - since it has no remaining threads to do anything else. However, even an unbounded thread - pool can run into trouble if it becomes too large. If you require the server to handle - many concurrent connections you should use NIO, not old IO.</para> - <para>When using new IO (NIO), ActiveMQ will, by default, cap its thread pool at three times - the number of cores (or hyper-threads) as reported by <literal> - Runtime.getRuntime().availableProcessors()</literal> for processing incoming packets. - To override this value, you can set the number of threads by specifying the parameter - <literal>nio-remoting-threads</literal> in the transport configuration. See the - <xref linkend="configuring-transports"/> for more information on this.</para> - <para>There are also a small number of other places where threads are used directly, we'll - discuss each in turn.</para> - <section id="server.scheduled.thread.pool"> - <title>Server Scheduled Thread Pool</title> - <para>The server scheduled thread pool is used for most activities on the server side - that require running periodically or with delays. It maps internally to a <literal - >java.util.concurrent.ScheduledThreadPoolExecutor</literal> instance.</para> - <para>The maximum number of thread used by this pool is configure in <literal - >activemq-configuration.xml</literal> with the <literal - >scheduled-thread-pool-max-size</literal> parameter. The default value is - <literal>5</literal> threads. A small number of threads is usually sufficient - for this pool.</para> - </section> - <section> - <title>General Purpose Server Thread Pool</title> - <para>This general purpose thread pool is used for most asynchronous actions on the - server side. It maps internally to a <literal - >java.util.concurrent.ThreadPoolExecutor</literal> instance.</para> - <para>The maximum number of thread used by this pool is configure in <literal - >activemq-configuration.xml</literal> with the <literal - >thread-pool-max-size</literal> parameter.</para> - <para>If a value of <literal>-1</literal> is used this signifies that the thread pool - has no upper bound and new threads will be created on demand if there are not enough - threads available to satisfy a request. If activity later subsides then threads are - timed-out and closed.</para> - <para>If a value of <literal>n</literal> where <literal>n</literal>is a positive integer - greater than zero is used this signifies that the thread pool is bounded. If more - requests come in and there are no free threads in the pool and the pool is full then - requests will block until a thread becomes available. It is recommended that a - bounded thread pool is used with caution since it can lead to dead-lock situations - if the upper bound is chosen to be too low.</para> - <para>The default value for <literal>thread-pool-max-size</literal> is <literal - >30</literal>.</para> - <para>See the <ulink - url="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.htm" - >J2SE javadoc</ulink> for more information on unbounded (cached), and bounded - (fixed) thread pools.</para> - </section> - <section> - <title>Expiry Reaper Thread</title> - <para>A single thread is also used on the server side to scan for expired messages in - queues. We cannot use either of the thread pools for this since this thread needs to - run at its own configurable priority.</para> - <para>For more information on configuring the reaper, please see <xref - linkend="message-expiry"/>.</para> - </section> - <section> - <title>Asynchronous IO</title> - <para>Asynchronous IO has a thread pool for receiving and dispatching events out of the - native layer. You will find it on a thread dump with the prefix - ActiveMQ-AIO-poller-pool. ActiveMQ uses one thread per opened file on the journal - (there is usually one).</para> - <para>There is also a single thread used to invoke writes on libaio. We do that to avoid - context switching on libaio that would cause performance issues. You will find this - thread on a thread dump with the prefix ActiveMQ-AIO-writer-pool.</para> - </section> - </section> - <section id="thread-pooling.client.side"> - <title>Client-Side Thread Management</title> - <para>On the client side, ActiveMQ maintains a single static scheduled thread pool and a - single static general thread pool for use by all clients using the same classloader in - that JVM instance.</para> - <para>The static scheduled thread pool has a maximum size of <literal>5</literal> threads, - and the general purpose thread pool has an unbounded maximum size.</para> - <para>If required ActiveMQ can also be configured so that each <literal - >ClientSessionFactory</literal> instance does not use these static pools but instead - maintains its own scheduled and general purpose pool. Any sessions created from that - <literal>ClientSessionFactory</literal> will use those pools instead.</para> - <para>To configure a <literal>ClientSessionFactory</literal> instance to use its own pools, - simply use the appropriate setter methods immediately after creation, for - example:</para> - <programlisting> -ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(...) -ClientSessionFactory myFactory = locator.createClientSessionFactory(); -myFactory.setUseGlobalPools(false); -myFactory.setScheduledThreadPoolMaxSize(10); -myFactory.setThreadPoolMaxSize(-1); </programlisting> - <para>If you're using the JMS API, you can set the same parameters on the - ClientSessionFactory and use it to create the <literal>ConnectionFactory</literal> - instance, for example:</para> - <programlisting> -ConnectionFactory myConnectionFactory = ActiveMQJMSClient.createConnectionFactory(myFactory);</programlisting> - <para>If you're using JNDI to instantiate <literal>ActiveMQConnectionFactory</literal> - instances, you can also set these parameters in the JNDI context environment, e.g. - <literal>jndi.properties</literal>. Here's a simple example using the "ConnectionFactory" connection - factory which is available in the context by default:</para> - <programlisting> -java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory -java.naming.provider.url=tcp://localhost:5445 -connection.ConnectionFactory.useGlobalPools=false -connection.ConnectionFactory.scheduledThreadPoolMaxSize=10 -connection.ConnectionFactory.threadPoolMaxSize=-1</programlisting> - </section> -</chapter>
http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/tools.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/tools.md b/docs/user-manual/en/tools.md new file mode 100644 index 0000000..a97aa79 --- /dev/null +++ b/docs/user-manual/en/tools.md @@ -0,0 +1,88 @@ +Tools +===== + +ActiveMQ ships with several helpful command line tools. All tools are +available from the activemq-tools-\<version\>-jar-with-dependencies.jar. +As the name suggests, this Java archive contains ActiveMQ along with all +of its dependencies. This is done to simplify the execution of the tools +by eliminating the need so specify a classpath. These tools are: + +- **`print-data`**. Used for low-level inspection of the bindings and + message journals. It takes two parameters - `bindings-directory` and + `journal-directory`. These are the paths to the directories where + the bindings and message journals are stored, respectively. For + example: + + java -jar activemq-tools-<version>-jar-with-dependencies.jar print-data /home/user/activemq/data/bindings /home/user/activemq/data/journal + +- **`print-pages`**. Used for low-level inspection of paged message + data. It takes two parameters - `paging-directory` and + `journal-directory`. These are the paths to the directories where + paged messages and the message journals are stored, respectively. + For example: + + java -jar activemq-tools-<version>-jar-with-dependencies.jar print-pages /home/user/activemq/data/paging-directory /home/user/activemq/data/journal + +- **`export`**. Used for exporting all binding and message data + (including paged and large messages) as well as JMS destinations and + connection factories (including JNDI bindings). The export is + structured as XML. This data can then be imported to another server + even if the server is a different version than the original. It + takes 4 parameters: + + - `bindings-directory` - the path to the bindings directory. + + - `journal-directory` - the path to the journal directory. + + - `paging-directory` - the path to the paging directory. + + - `large-messages-directory` - the path to the large-messages + directory. + + Here's an example: + + java -jar activemq-tools-<version>-jar-with-dependencies.jar export /home/user/activemq/data/bindings-directory /home/user/activemq/data/journal-directory /home/user/activemq/data/paging-directory /home/user/activemq/data/large-messages + + This tool will export directly to standard out so if the data needs + to be stored in a file please redirect as appropriate for the + operation system in use. Also, please note that the `export` tool is + single threaded so depending on the size of the journal it could + take awhile to complete. + +- **`import`**. Used for importing data from an XML document generated + by the `export` tool. The `import` tool reads the XML document and + connects to a ActiveMQ server via Netty to import all the data. It + takes 5 parameters: + + - `input-file` - the path to the XML file generated by the + `export` tool. + + - `host` - the IP address or hostname of the server where the data + should be imported. + + - `port` - the port where ActiveMQ is listening. + + - `transactional` - a `boolean` flag to indicate whether or not to + send all the *message* data in a single transaction. Valid + values are `true` or `false`. + + - `application-server-compatibility` - a `boolean` flag to + indicate whether or not JNDI bindings need special treatment to + account for the way JBoss AS7, Wildfly, and JBoss EAP 6 handle + JNDI for remote clients. Each of these application servers + require a special JNDI binding to allow access from remote + clients. If this is `true` then every JNDI binding in the XML + will be duplicated in the "java:jboss/exported/" namespace thus + allowing both local and remote clients to use the same name when + accessing resources via JNDI. Valid values are `true` or + `false`. + + Here's an example: + + java -jar activemq-tools-<version>-jar-with-dependencies.jar import /home/user/exportData.xml 127.0.0.1 5445 false false + + Like the `export` tool the `import` tool is single threaded so + depending on the size of the XML file it may take awhile for the + process to complete. + + http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/tools.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/tools.xml b/docs/user-manual/en/tools.xml deleted file mode 100644 index 3bd3148..0000000 --- a/docs/user-manual/en/tools.xml +++ /dev/null @@ -1,116 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ============================================================================= --> -<!-- 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. --> -<!-- ============================================================================= --> - -<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ - <!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent"> - %BOOK_ENTITIES; - ]> -<chapter id="tools"> - <title>Tools</title> - - <para>ActiveMQ ships with several helpful command line tools. All tools are available from the activemq-tools-<version>-jar-with-dependencies.jar. - As the name suggests, this Java archive contains ActiveMQ along with all of its dependencies. This is done to - simplify the execution of the tools by eliminating the need so specify a classpath. These tools are:</para> - <itemizedlist> - <listitem> - <para><emphasis role="bold"><literal>print-data</literal></emphasis>. Used for low-level inspection of the bindings and message journals. It - takes two parameters - <literal>bindings-directory</literal> and <literal>journal-directory</literal>. These - are the paths to the directories where the bindings and message journals are stored, respectively. For - example: - </para> - <programlisting>java -jar activemq-tools-<version>-jar-with-dependencies.jar print-data /home/user/activemq/data/bindings /home/user/activemq/data/journal</programlisting> - </listitem> - <listitem> - <para><emphasis role="bold"><literal>print-pages</literal></emphasis>. Used for low-level inspection of paged message data. It takes two - parameters - <literal>paging-directory</literal> and <literal>journal-directory</literal>. These are the - paths to the directories where paged messages and the message journals are stored, respectively. For - example: - </para> - <programlisting>java -jar activemq-tools-<version>-jar-with-dependencies.jar print-pages /home/user/activemq/data/paging-directory /home/user/activemq/data/journal</programlisting> - </listitem> - <listitem> - <para><emphasis role="bold"><literal>export</literal></emphasis>. Used for exporting all binding and message data (including paged and large - messages) as well as JMS destinations and connection factories (including JNDI bindings). The export is - structured as XML. This data can then be imported to another server even if the server is a different - version than the original. It takes 4 parameters: - </para> - <itemizedlist> - <listitem> - <para><literal>bindings-directory</literal> - the path to the bindings directory.</para> - </listitem> - <listitem> - <para><literal>journal-directory</literal> - the path to the journal directory.</para> - </listitem> - <listitem> - <para><literal>paging-directory</literal> - the path to the paging directory.</para> - </listitem> - <listitem> - <para><literal>large-messages-directory</literal> - the path to the large-messages directory.</para> - </listitem> - </itemizedlist> - <para>Here's an example:</para> - <programlisting>java -jar activemq-tools-<version>-jar-with-dependencies.jar export /home/user/activemq/data/bindings-directory /home/user/activemq/data/journal-directory /home/user/activemq/data/paging-directory /home/user/activemq/data/large-messages</programlisting> - <para>This tool will export directly to standard out so if the data needs to be stored in a file please - redirect as appropriate for the operation system in use. Also, please note that the <literal>export</literal> - tool is single threaded so depending on the size of the journal it could take awhile to complete. - </para> - </listitem> - <listitem> - <para><emphasis role="bold"><literal>import</literal></emphasis>. Used for importing data from an XML document generated by the - <literal>export</literal> tool. The <literal>import</literal> tool reads the XML document and connects - to a ActiveMQ server via Netty to import all the data. It takes 5 parameters: - </para> - <itemizedlist> - <listitem> - <para><literal>input-file</literal> - the path to the XML file generated by the <literal>export</literal> - tool. - </para> - </listitem> - <listitem> - <para><literal>host</literal> - the IP address or hostname of the server where the data should be - imported. - </para> - </listitem> - <listitem> - <para><literal>port</literal> - the port where ActiveMQ is listening.</para> - </listitem> - <listitem> - <para><literal>transactional</literal> - a <literal>boolean</literal> flag to indicate whether or not to - send all the <emphasis>message</emphasis> data in a single transaction. Valid values are <literal>true</literal> - or <literal>false</literal>. - </para> - </listitem> - <listitem> - <para><literal>application-server-compatibility</literal> - a <literal>boolean</literal> flag to indicate - whether or not JNDI bindings need special treatment to account for the way JBoss AS7, Wildfly, and - JBoss EAP 6 handle JNDI for remote clients. Each of these application servers require a special JNDI - binding to allow access from remote clients. If this is <literal>true</literal> then every JNDI - binding in the XML will be duplicated in the "java:jboss/exported/" namespace thus allowing both local - and remote clients to use the same name when accessing resources via JNDI. Valid values are - <literal>true</literal> or <literal>false</literal>. - </para> - </listitem> - </itemizedlist> - <para>Here's an example:</para> - <programlisting>java -jar activemq-tools-<version>-jar-with-dependencies.jar import /home/user/exportData.xml 127.0.0.1 5445 false false</programlisting> - <para>Like the <literal>export</literal> tool the <literal>import</literal> tool is single threaded so - depending on the size of the XML file it may take awhile for the process to complete. - </para> - </listitem> - </itemizedlist> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/transaction-config.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/transaction-config.md b/docs/user-manual/en/transaction-config.md new file mode 100644 index 0000000..3bdbbc8 --- /dev/null +++ b/docs/user-manual/en/transaction-config.md @@ -0,0 +1,22 @@ +Resource Manager Configuration +============================== + +ActiveMQ has its own Resource Manager for handling the lifespan of JTA +transactions. When a transaction is started the resource manager is +notified and keeps a record of the transaction and its current state. It +is possible in some cases for a transaction to be started but then +forgotten about. Maybe the client died and never came back. If this +happens then the transaction will just sit there indefinitely. + +To cope with this ActiveMQ can, if configured, scan for old transactions +and rollback any it finds. The default for this is 3000000 milliseconds +(5 minutes), i.e. any transactions older than 5 minutes are removed. +This timeout can be changed by editing the `transaction-timeout` +property in `activemq-configuration.xml` (value must be in +milliseconds). The property `transaction-timeout-scan-period` configures +how often, in milliseconds, to scan for old transactions. + +Please note that ActiveMQ will not unilaterally rollback any XA +transactions in a prepared state - this must be heuristically rolled +back via the management API if you are sure they will never be resolved +by the transaction manager. http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/transaction-config.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/transaction-config.xml b/docs/user-manual/en/transaction-config.xml deleted file mode 100644 index 1d4def2..0000000 --- a/docs/user-manual/en/transaction-config.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ============================================================================= --> -<!-- 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. --> -<!-- ============================================================================= --> - -<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ -<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent"> -%BOOK_ENTITIES; -]> -<chapter id="transaction-config"> - <title>Resource Manager Configuration</title> - <para>ActiveMQ has its own Resource Manager for handling the lifespan of JTA transactions. When a - transaction is started the resource manager is notified and keeps a record of the - transaction and its current state. It is possible in some cases for a transaction to be - started but then forgotten about. Maybe the client died and never came back. If this happens - then the transaction will just sit there indefinitely.</para> - <para>To cope with this ActiveMQ can, if configured, scan for old transactions and rollback any - it finds. The default for this is 3000000 milliseconds (5 minutes), i.e. any transactions older - than 5 minutes are removed. This timeout can be changed by editing the <literal - >transaction-timeout</literal> property in <literal>activemq-configuration.xml</literal> (value must be in milliseconds). - The property <literal>transaction-timeout-scan-period</literal> configures how often, in - milliseconds, to scan for old transactions.</para> - <para>Please note that ActiveMQ will not unilaterally rollback any XA transactions in a prepared state - this must be heuristically rolled - back via the management API if you are sure they will never be resolved by the transaction manager.</para> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/undelivered-messages.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/undelivered-messages.md b/docs/user-manual/en/undelivered-messages.md new file mode 100644 index 0000000..d449102 --- /dev/null +++ b/docs/user-manual/en/undelivered-messages.md @@ -0,0 +1,166 @@ +Message Redelivery and Undelivered Messages +=========================================== + +Messages can be delivered unsuccessfully (e.g. if the transacted session +used to consume them is rolled back). Such a message goes back to its +queue ready to be redelivered. However, this means it is possible for a +message to be delivered again and again without any success and remain +in the queue, clogging the system. + +There are 2 ways to deal with these undelivered messages: + +- Delayed redelivery. + + It is possible to delay messages redelivery to let the client some + time to recover from transient failures and not overload its network + or CPU resources + +- Dead Letter Address. + + It is also possible to configure a dead letter address so that after + a specified number of unsuccessful deliveries, messages are removed + from the queue and will not be delivered again + +Both options can be combined for maximum flexibility. + +Delayed Redelivery +================== + +Delaying redelivery can often be useful in the case that clients +regularly fail or rollback. Without a delayed redelivery, the system can +get into a "thrashing" state, with delivery being attempted, the client +rolling back, and delivery being re-attempted ad infinitum in quick +succession, consuming valuable CPU and network resources. + +Configuring Delayed Redelivery +------------------------------ + +Delayed redelivery is defined in the address-setting configuration: + + <!-- delay redelivery of messages for 5s --> + <address-setting match="jms.queue.exampleQueue"> + <!-- default is 1.0 --> + <redelivery-delay-multiplier>1.5</redelivery-delay-multiplier> + <!-- default is 0 (no delay) --> + <redelivery-delay>5000</redelivery-delay> + <!-- default is redelivery-delay * 10 --> + <max-redelivery-delay>50000</max-redelivery-delay> + + </address-setting> + +If a `redelivery-delay` is specified, ActiveMQ will wait this delay +before redelivering the messages. + +By default, there is no redelivery delay (`redelivery-delay`is set to +0). + +Other subsequent messages will be delivery regularly, only the cancelled +message will be sent asynchronously back to the queue after the delay. + +You can specify a multiplier that will take effect on top of the +redelivery-delay with a max-redelivery-delay to be taken into account. + +The max-redelivery-delay is defaulted to redelivery-delay \* 10 + +Address wildcards can be used to configure redelivery delay for a set of +addresses (see ?), so you don't have to specify redelivery delay +individually for each address. + +Example +------- + +See ? for an example which shows how delayed redelivery is configured +and used with JMS. + +Dead Letter Addresses +===================== + +To prevent a client infinitely receiving the same undelivered message +(regardless of what is causing the unsuccessful deliveries), messaging +systems define *dead letter addresses*: after a specified unsuccessful +delivery attempts, the message is removed from the queue and send +instead to a dead letter address. + +Any such messages can then be diverted to queue(s) where they can later +be perused by the system administrator for action to be taken. + +ActiveMQ's addresses can be assigned a dead letter address. Once the +messages have been unsuccessfully delivered for a given number of +attempts, they are removed from the queue and sent to the dead letter +address. These *dead letter* messages can later be consumed for further +inspection. + +Configuring Dead Letter Addresses +--------------------------------- + +Dead letter address is defined in the address-setting configuration: + + <!-- undelivered messages in exampleQueue will be sent to the dead letter address + deadLetterQueue after 3 unsuccessful delivery attempts --> + <address-setting match="jms.queue.exampleQueue"> + <dead-letter-address>jms.queue.deadLetterQueue</dead-letter-address> + <max-delivery-attempts>3</max-delivery-attempts> + </address-setting> + +If a `dead-letter-address` is not specified, messages will removed after +`max-delivery-attempts` unsuccessful attempts. + +By default, messages are redelivered 10 times at the maximum. Set +`max-delivery-attempts` to -1 for infinite redeliveries. + +For example, a dead letter can be set globally for a set of matching +addresses and you can set `max-delivery-attempts` to -1 for a specific +address setting to allow infinite redeliveries only for this address. + +Address wildcards can be used to configure dead letter settings for a +set of addresses (see ?). + +Dead Letter Properties +---------------------- + +Dead letter messages which are consumed from a dead letter address have +the following properties: + +- `_HQ_ORIG_ADDRESS` + + a String property containing the *original address* of the dead + letter message + +- `_HQ_ORIG_QUEUE` + + a String property containing the *original queue* of the dead letter + message + +Example +------- + +See ? for an example which shows how dead letter is configured and used +with JMS. + +Delivery Count Persistence +========================== + +In normal use, ActiveMQ does not update delivery count *persistently* +until a message is rolled back (i.e. the delivery count is not updated +*before* the message is delivered to the consumer). In most messaging +use cases, the messages are consumed, acknowledged and forgotten as soon +as they are consumed. In these cases, updating the delivery count +persistently before delivering the message would add an extra persistent +step *for each message delivered*, implying a significant performance +penalty. + +However, if the delivery count is not updated persistently before the +message delivery happens, in the event of a server crash, messages might +have been delivered but that will not have been reflected in the +delivery count. During the recovery phase, the server will not have +knowledge of that and will deliver the message with `redelivered` set to +`false` while it should be `true`. + +As this behavior breaks strict JMS semantics, ActiveMQ allows to persist +delivery count before message delivery but disabled it by default for +performance implications. + +To enable it, set `persist-delivery-count-before-delivery` to `true` in +`activemq-configuration.xml`: + + <persist-delivery-count-before-delivery>true</persist-delivery-count-before-delivery> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/undelivered-messages.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/undelivered-messages.xml b/docs/user-manual/en/undelivered-messages.xml deleted file mode 100644 index 2f4a6f5..0000000 --- a/docs/user-manual/en/undelivered-messages.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ============================================================================= --> -<!-- 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. --> -<!-- ============================================================================= --> - -<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ -<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent"> -%BOOK_ENTITIES; -]> -<chapter id="undelivered-messages"> - <title>Message Redelivery and Undelivered Messages</title> - <para>Messages can be delivered unsuccessfully (e.g. if the transacted session used to consume - them is rolled back). Such a message goes back to its queue ready to be redelivered. However, - this means it is possible for a message to be delivered again and again without any success - and remain in the queue, clogging the system.</para> - <para>There are 2 ways to deal with these undelivered messages:</para> - <itemizedlist> - <listitem> - <para>Delayed redelivery.</para> - <para>It is possible to delay messages redelivery to let the client some time to recover - from transient failures and not overload its network or CPU resources</para> - </listitem> - <listitem> - <para>Dead Letter Address.</para> - <para>It is also possible to configure a dead letter address so that after a specified - number of unsuccessful deliveries, messages are removed from the queue and will not be - delivered again</para> - </listitem> - </itemizedlist> - <para>Both options can be combined for maximum flexibility.</para> - <section> - <title>Delayed Redelivery</title> - <para>Delaying redelivery can often be useful in the case that clients regularly fail or - rollback. Without a delayed redelivery, the system can get into a "thrashing" state, with - delivery being attempted, the client rolling back, and delivery being re-attempted ad - infinitum in quick succession, consuming valuable CPU and network resources.</para> - <section id="undelivered-messages.delay"> - <title>Configuring Delayed Redelivery</title> - <para>Delayed redelivery is defined in the address-setting configuration:</para> - <programlisting> -<!-- delay redelivery of messages for 5s --> -<address-setting match="jms.queue.exampleQueue"> - <!-- default is 1.0 --> - <redelivery-delay-multiplier>1.5</redelivery-delay-multiplier> - <!-- default is 0 (no delay) --> - <redelivery-delay>5000</redelivery-delay> - <!-- default is redelivery-delay * 10 --> - <max-redelivery-delay>50000</max-redelivery-delay> - -</address-setting></programlisting> - <para>If a <literal>redelivery-delay</literal> is specified, ActiveMQ will wait this delay - before redelivering the messages.</para> - <para>By default, there is no redelivery delay (<literal>redelivery-delay</literal>is set - to 0).</para> - <para>Other subsequent messages will be delivery regularly, only the cancelled message - will be sent asynchronously back to the queue after the delay.</para> - <para>You can specify a multiplier that will take effect on top of the redelivery-delay - with a max-redelivery-delay to be taken into account.</para> - <para>The max-redelivery-delay is defaulted to redelivery-delay * 10</para> - <para>Address wildcards can be used to configure redelivery delay for a set of addresses - (see <xref linkend="wildcard-syntax"/>), so you don't have to specify redelivery delay - individually for each address.</para> - </section> - <section> - <title>Example</title> - <para>See <xref linkend="examples.delayed-redelivery"/> for an example which shows how - delayed redelivery is configured and used with JMS.</para> - </section> - </section> - <section> - <title>Dead Letter Addresses</title> - <para>To prevent a client infinitely receiving the same undelivered message (regardless of - what is causing the unsuccessful deliveries), messaging systems define <emphasis - role="italic">dead letter addresses</emphasis>: after a specified unsuccessful delivery - attempts, the message is removed from the queue and send instead to a dead letter address. </para> - <para>Any such messages can then be diverted to queue(s) where they can later be perused by - the system administrator for action to be taken.</para> - <para>ActiveMQ's addresses can be assigned a dead letter address. Once the messages have been - unsuccessfully delivered for a given number of attempts, they are removed from the queue - and sent to the dead letter address. These <emphasis>dead letter</emphasis> messages can - later be consumed for further inspection.</para> - <section id="undelivered-messages.configuring"> - <title>Configuring Dead Letter Addresses</title> - <para>Dead letter address is defined in the address-setting configuration:</para> - <programlisting> -<!-- undelivered messages in exampleQueue will be sent to the dead letter address - deadLetterQueue after 3 unsuccessful delivery attempts --> -<address-setting match="jms.queue.exampleQueue"> - <dead-letter-address>jms.queue.deadLetterQueue</dead-letter-address> - <max-delivery-attempts>3</max-delivery-attempts> -</address-setting></programlisting> - <para>If a <literal>dead-letter-address</literal> is not specified, messages will removed - after <literal>max-delivery-attempts</literal> unsuccessful attempts.</para> - <para>By default, messages are redelivered 10 times at the maximum. Set <literal - >max-delivery-attempts</literal> to -1 for infinite redeliveries.</para> - <para>For example, a dead letter can be set globally for a set of matching addresses and - you can set <literal>max-delivery-attempts</literal> to -1 for a specific address - setting to allow infinite redeliveries only for this address.</para> - <para>Address wildcards can be used to configure dead letter settings for a set of - addresses (see <xref linkend="wildcard-syntax"/>).</para> - </section> - <section> - <title>Dead Letter Properties</title> - <para>Dead letter messages which are consumed from a dead letter address have the following - properties:</para> - <itemizedlist> - <listitem> - <para><literal>_HQ_ORIG_ADDRESS</literal></para> - <para>a String property containing the <emphasis>original address</emphasis> of - the dead letter message</para> - </listitem> - <listitem> - <para><literal>_HQ_ORIG_QUEUE</literal></para> - <para>a String property containing the <emphasis>original queue</emphasis> of - the dead letter message</para> - </listitem> - </itemizedlist> - </section> - <section> - <title>Example</title> - <para>See <xref linkend="examples.dead-letter"/> for an example which shows how dead letter - is configured and used with JMS.</para> - </section> - </section> - <section id="configuring.delivery.count.persistence"> - <title>Delivery Count Persistence</title> - <para>In normal use, ActiveMQ does not update delivery count <emphasis>persistently</emphasis> - until a message is rolled back (i.e. the delivery count is not updated - <emphasis>before</emphasis> the message is delivered to the consumer). In most messaging - use cases, the messages are consumed, acknowledged and forgotten as soon as they are - consumed. In these cases, updating the delivery count persistently before delivering the - message would add an extra persistent step <emphasis>for each message delivered</emphasis>, - implying a significant performance penalty.</para> - <para>However, if the delivery count is not updated persistently before the message delivery - happens, in the event of a server crash, messages might have been delivered but that will - not have been reflected in the delivery count. During the recovery phase, the server will - not have knowledge of that and will deliver the message with <literal>redelivered</literal> - set to <literal>false</literal> while it should be <literal>true</literal>. </para> - <para>As this behavior breaks strict JMS semantics, ActiveMQ allows to persist delivery count - before message delivery but disabled it by default for performance implications.</para> - <para>To enable it, set <literal>persist-delivery-count-before-delivery</literal> to <literal - >true</literal> in <literal>activemq-configuration.xml</literal>:</para> - <programlisting> -<persist-delivery-count-before-delivery>true</persist-delivery-count-before-delivery></programlisting> - </section> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/using-core.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/using-core.md b/docs/user-manual/en/using-core.md new file mode 100644 index 0000000..6c9743f --- /dev/null +++ b/docs/user-manual/en/using-core.md @@ -0,0 +1,222 @@ +Using Core +========== + +ActiveMQ core is a completely JMS-agnostic messaging system with its own +non-JMS API. We call this the *core API*. + +If you don't want to use JMS you can use the core API directly. The core +API provides all the functionality of JMS but without much of the +complexity. It also provides features that are not available using JMS. + +Core Messaging Concepts +======================= + +Some of the core messaging concepts are similar to JMS concepts, but +core messaging concepts differ in some ways. In general the core +messaging API is simpler than the JMS API, since we remove distinctions +between queues, topics and subscriptions. We'll discuss each of the +major core messaging concepts in turn, but to see the API in detail, +please consult the Javadoc. + +Message +------- + +- A message is the unit of data which is sent between clients and + servers. + +- A message has a body which is a buffer containing convenient methods + for reading and writing data into it. + +- A message has a set of properties which are key-value pairs. Each + property key is a string and property values can be of type integer, + long, short, byte, byte[], String, double, float or boolean. + +- A message has an *address* it is being sent to. When the message + arrives on the server it is routed to any queues that are bound to + the address - if the queues are bound with any filter, the message + will only be routed to that queue if the filter matches. An address + may have many queues bound to it or even none. There may also be + entities other than queues, like *diverts* bound to addresses. + +- Messages can be either durable or non durable. Durable messages in a + durable queue will survive a server crash or restart. Non durable + messages will never survive a server crash or restart. + +- Messages can be specified with a priority value between 0 and 9. 0 + represents the lowest priority and 9 represents the highest. + ActiveMQ will attempt to deliver higher priority messages before + lower priority ones. + +- Messages can be specified with an optional expiry time. ActiveMQ + will not deliver messages after its expiry time has been exceeded. + +- Messages also have an optional timestamp which represents the time + the message was sent. + +- ActiveMQ also supports the sending/consuming of very large messages + - much larger than can fit in available RAM at any one time. + +Address +------- + +A server maintains a mapping between an address and a set of queues. +Zero or more queues can be bound to a single address. Each queue can be +bound with an optional message filter. When a message is routed, it is +routed to the set of queues bound to the message's address. If any of +the queues are bound with a filter expression, then the message will +only be routed to the subset of bound queues which match that filter +expression. + +Other entities, such as *diverts* can also be bound to an address and +messages will also be routed there. + +> **Note** +> +> In core, there is no concept of a Topic, Topic is a JMS only term. +> Instead, in core, we just deal with *addresses* and *queues*. +> +> For example, a JMS topic would be implemented by a single address to +> which many queues are bound. Each queue represents a subscription of +> the topic. A JMS Queue would be implemented as a single address to +> which one queue is bound - that queue represents the JMS queue. + +Queue +----- + +Queues can be durable, meaning the messages they contain survive a +server crash or restart, as long as the messages in them are durable. +Non durable queues do not survive a server restart or crash even if the +messages they contain are durable. + +Queues can also be temporary, meaning they are automatically deleted +when the client connection is closed, if they are not explicitly deleted +before that. + +Queues can be bound with an optional filter expression. If a filter +expression is supplied then the server will only route messages that +match that filter expression to any queues bound to the address. + +Many queues can be bound to a single address. A particular queue is only +bound to a maximum of one address. + +ServerLocator +------------- + +Clients use `ServerLocator` instances to create `ClientSessionFactory` +instances. `ServerLocator` instances are used to locate servers and +create connections to them. + +In JMS terms think of a `ServerLocator` in the same way you would a JMS +Connection Factory. + +`ServerLocator` instances are created using the `ActiveMQClient` factory +class. + +ClientSessionFactory +-------------------- + +Clients use `ClientSessionFactory` instances to create `ClientSession` +instances. `ClientSessionFactory` instances are basically the connection +to a server + +In JMS terms think of them as JMS Connections. + +`ClientSessionFactory` instances are created using the `ServerLocator` +class. + +ClientSession +------------- + +A client uses a ClientSession for consuming and producing messages and +for grouping them in transactions. ClientSession instances can support +both transactional and non transactional semantics and also provide an +`XAResource` interface so messaging operations can be performed as part +of a +[JTA](http://www.oracle.com/technetwork/java/javaee/tech/jta-138684.html) +transaction. + +ClientSession instances group ClientConsumers and ClientProducers. + +ClientSession instances can be registered with an optional +`SendAcknowledgementHandler`. This allows your client code to be +notified asynchronously when sent messages have successfully reached the +server. This unique ActiveMQ feature, allows you to have full guarantees +that sent messages have reached the server without having to block on +each message sent until a response is received. Blocking on each +messages sent is costly since it requires a network round trip for each +message sent. By not blocking and receiving send acknowledgements +asynchronously you can create true end to end asynchronous systems which +is not possible using the standard JMS API. For more information on this +advanced feature please see the section ?. + +ClientConsumer +-------------- + +Clients use `ClientConsumer` instances to consume messages from a queue. +Core Messaging supports both synchronous and asynchronous message +consumption semantics. `ClientConsumer` instances can be configured with +an optional filter expression and will only consume messages which match +that expression. + +ClientProducer +-------------- + +Clients create `ClientProducer` instances on `ClientSession` instances +so they can send messages. ClientProducer instances can specify an +address to which all sent messages are routed, or they can have no +specified address, and the address is specified at send time for the +message. + +> **Warning** +> +> Please note that ClientSession, ClientProducer and ClientConsumer +> instances are *designed to be re-used*. +> +> It's an anti-pattern to create new ClientSession, ClientProducer and +> ClientConsumer instances for each message you produce or consume. If +> you do this, your application will perform very poorly. This is +> discussed further in the section on performance tuning ?. + +A simple example of using Core +============================== + +Here's a very simple program using the core messaging API to send and +receive a message. Logically it's comprised of two sections: firstly +setting up the producer to write a message to an *addresss*, and +secondly, creating a *queue* for the consumer, creating the consumer and +*starting* it. + + ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration( + InVMConnectorFactory.class.getName())); + + // In this simple example, we just use one session for both producing and receiving + + ClientSessionFactory factory = locator.createClientSessionFactory(); + ClientSession session = factory.createSession(); + + // A producer is associated with an address ... + + ClientProducer producer = session.createProducer("example"); + ClientMessage message = session.createMessage(true); + message.getBodyBuffer().writeString("Hello"); + + // We need a queue attached to the address ... + + session.createQueue("example", "example", true); + + // And a consumer attached to the queue ... + + ClientConsumer consumer = session.createConsumer("example"); + + // Once we have a queue, we can send the message ... + + producer.send(message); + + // We need to start the session before we can -receive- messages ... + + session.start(); + ClientMessage msgReceived = consumer.receive(); + + System.out.println("message = " + msgReceived.getBodyBuffer().readString()); + + session.close(); http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/using-core.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/using-core.xml b/docs/user-manual/en/using-core.xml deleted file mode 100644 index f66f6af..0000000 --- a/docs/user-manual/en/using-core.xml +++ /dev/null @@ -1,223 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ============================================================================= --> -<!-- 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. --> -<!-- ============================================================================= --> -<chapter id="using-core"> - <title>Using Core</title> - <para>ActiveMQ core is a completely JMS-agnostic messaging system with its own non-JMS API. We - call this the <emphasis>core API</emphasis>.</para> - <para>If you don't want to use JMS you can use the core API directly. The core API provides all - the functionality of JMS but without much of the complexity. It also provides features that - are not available using JMS.</para> - <section> - <title>Core Messaging Concepts</title> - <para>Some of the core messaging concepts are similar to JMS concepts, but core messaging - concepts differ in some ways. In general the core messaging API is simpler than the JMS - API, since we remove distinctions between queues, topics and subscriptions. We'll - discuss each of the major core messaging concepts in turn, but to see the API in detail, - please consult the Javadoc.</para> - <section> - <title>Message</title> - <itemizedlist> - <listitem> - <para>A message is the unit of data which is sent between clients and - servers.</para> - </listitem> - <listitem> - <para>A message has a body which is a buffer containing convenient methods for - reading and writing data into it.</para> - </listitem> - <listitem> - <para>A message has a set of properties which are key-value pairs. Each property - key is a string and property values can be of type integer, long, short, - byte, byte[], String, double, float or boolean.</para> - </listitem> - <listitem> - <para>A message has an <emphasis>address</emphasis> it is being sent to. When - the message arrives on the server it is routed to any queues that are bound - to the address - if the queues are bound with any filter, the message will - only be routed to that queue if the filter matches. An address may have many - queues bound to it or even none. There may also be entities other than - queues, like <emphasis role="italic">diverts</emphasis> bound to - addresses.</para> - </listitem> - <listitem> - <para>Messages can be either durable or non durable. Durable messages in a - durable queue will survive a server crash or restart. Non durable messages - will never survive a server crash or restart.</para> - </listitem> - <listitem> - <para>Messages can be specified with a priority value between 0 and 9. 0 - represents the lowest priority and 9 represents the highest. ActiveMQ will - attempt to deliver higher priority messages before lower priority - ones.</para> - </listitem> - <listitem> - <para>Messages can be specified with an optional expiry time. ActiveMQ will not - deliver messages after its expiry time has been exceeded.</para> - </listitem> - <listitem> - <para>Messages also have an optional timestamp which represents the time the - message was sent.</para> - </listitem> - <listitem> - <para>ActiveMQ also supports the sending/consuming of very large messages - much - larger than can fit in available RAM at any one time.</para> - </listitem> - </itemizedlist> - </section> - <section> - <title>Address</title> - <para>A server maintains a mapping between an address and a set of queues. Zero or more - queues can be bound to a single address. Each queue can be bound with an optional - message filter. When a message is routed, it is routed to the set of queues bound to - the message's address. If any of the queues are bound with a filter expression, then - the message will only be routed to the subset of bound queues which match that - filter expression.</para> - <para>Other entities, such as <emphasis role="italic">diverts</emphasis> can also be - bound to an address and messages will also be routed there.</para> - <note> - <para>In core, there is no concept of a Topic, Topic is a JMS only term. Instead, in - core, we just deal with <emphasis>addresses</emphasis> and - <emphasis>queues</emphasis>.</para> - <para>For example, a JMS topic would be implemented by a single address to which - many queues are bound. Each queue represents a subscription of the topic. A JMS - Queue would be implemented as a single address to which one queue is bound - - that queue represents the JMS queue.</para> - </note> - </section> - <section> - <title>Queue</title> - <para>Queues can be durable, meaning the messages they contain survive a server crash or - restart, as long as the messages in them are durable. Non durable queues do not - survive a server restart or crash even if the messages they contain are - durable.</para> - <para>Queues can also be temporary, meaning they are automatically deleted when the - client connection is closed, if they are not explicitly deleted before that.</para> - <para>Queues can be bound with an optional filter expression. If a filter expression is - supplied then the server will only route messages that match that filter expression - to any queues bound to the address.</para> - <para>Many queues can be bound to a single address. A particular queue is only bound to - a maximum of one address.</para> - </section> - <section> - <title>ServerLocator</title> - <para>Clients use <literal>ServerLocator</literal> instances to create <literal - >ClientSessionFactory</literal> instances. <literal>ServerLocator</literal> - instances are used to locate servers and create connections to them. </para> - <para>In JMS terms think of a <literal>ServerLocator</literal> in the same way you would - a JMS Connection Factory.</para> - <para><literal>ServerLocator</literal> instances are created using the <literal - >ActiveMQClient</literal> factory class.</para> - </section> - <section> - <title>ClientSessionFactory</title> - <para>Clients use <literal>ClientSessionFactory</literal> instances to create <literal - >ClientSession</literal> instances. <literal>ClientSessionFactory</literal> - instances are basically the connection to a server</para> - <para> In JMS terms think of them as JMS Connections.</para> - <para><literal>ClientSessionFactory</literal> instances are created using the <literal - >ServerLocator</literal> class.</para> - </section> - <section> - <title>ClientSession</title> - <para>A client uses a ClientSession for consuming and producing messages and for - grouping them in transactions. ClientSession instances can support both - transactional and non transactional semantics and also provide an <literal - >XAResource</literal> interface so messaging operations can be performed as part - of a <ulink url="http://www.oracle.com/technetwork/java/javaee/tech/jta-138684.html">JTA</ulink> - transaction.</para> - <para>ClientSession instances group ClientConsumers and ClientProducers.</para> - <para>ClientSession instances can be registered with an optional <literal - >SendAcknowledgementHandler</literal>. This allows your client code to be - notified asynchronously when sent messages have successfully reached the server. - This unique ActiveMQ feature, allows you to have full guarantees that sent messages - have reached the server without having to block on each message sent until a - response is received. Blocking on each messages sent is costly since it requires a - network round trip for each message sent. By not blocking and receiving send - acknowledgements asynchronously you can create true end to end asynchronous systems - which is not possible using the standard JMS API. For more information on this - advanced feature please see the section <xref linkend="send-guarantees"/>.</para> - </section> - <section> - <title>ClientConsumer</title> - <para>Clients use <literal>ClientConsumer</literal> instances to consume messages from a - queue. Core Messaging supports both synchronous and asynchronous message consumption - semantics. <literal>ClientConsumer</literal> instances can be configured with an - optional filter expression and will only consume messages which match that - expression.</para> - </section> - <section> - <title>ClientProducer</title> - <para>Clients create <literal>ClientProducer</literal> instances on <literal - >ClientSession</literal> instances so they can send messages. ClientProducer - instances can specify an address to which all sent messages are routed, or they can - have no specified address, and the address is specified at send time for the - message.</para> - </section> - <warning> - <para>Please note that ClientSession, ClientProducer and ClientConsumer instances are - <emphasis>designed to be re-used</emphasis>.</para> - <para>It's an anti-pattern to create new ClientSession, ClientProducer and - ClientConsumer instances for each message you produce or consume. If you do this, - your application will perform very poorly. This is discussed further in the section - on performance tuning <xref linkend="perf-tuning"/>.</para> - </warning> - </section> - <section> - <title>A simple example of using Core</title> - <para>Here's a very simple program using the core messaging API to send and receive a - message. Logically it's comprised of two sections: firstly setting up the producer to - write a message to an <emphasis>addresss</emphasis>, and secondly, creating a - <emphasis>queue</emphasis> for the consumer, creating the consumer and - <emphasis>starting</emphasis> it.</para> - <programlisting> -ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration( - InVMConnectorFactory.class.getName())); - -// In this simple example, we just use one session for both producing and receiving - -ClientSessionFactory factory = locator.createClientSessionFactory(); -ClientSession session = factory.createSession(); - -// A producer is associated with an address ... - -ClientProducer producer = session.createProducer("example"); -ClientMessage message = session.createMessage(true); -message.getBodyBuffer().writeString("Hello"); - -// We need a queue attached to the address ... - -session.createQueue("example", "example", true); - -// And a consumer attached to the queue ... - -ClientConsumer consumer = session.createConsumer("example"); - -// Once we have a queue, we can send the message ... - -producer.send(message); - -// We need to start the session before we can -receive- messages ... - -session.start(); -ClientMessage msgReceived = consumer.receive(); - -System.out.println("message = " + msgReceived.getBodyBuffer().readString()); - -session.close();</programlisting> - </section> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/using-jms.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/using-jms.md b/docs/user-manual/en/using-jms.md new file mode 100644 index 0000000..595dc0e --- /dev/null +++ b/docs/user-manual/en/using-jms.md @@ -0,0 +1,410 @@ +Using JMS +========= + +Although ActiveMQ provides a JMS agnostic messaging API, many users will +be more comfortable using JMS. + +JMS is a very popular API standard for messaging, and most messaging +systems provide a JMS API. If you are completely new to JMS we suggest +you follow the[Sun JMS +tutorial](http://docs.oracle.com/javaee/1.3/jms/tutorial) - a full JMS +tutorial is out of scope for this guide. + +ActiveMQ also ships with a wide range of examples, many of which +demonstrate JMS API usage. A good place to start would be to play around +with the simple JMS Queue and Topic example, but we also provide +examples for many other parts of the JMS API. A full description of the +examples is available in ?. + +In this section we'll go through the main steps in configuring the +server for JMS and creating a simple JMS program. We'll also show how to +configure and use JNDI, and also how to use JMS with ActiveMQ without +using any JNDI. + +A simple ordering system +======================== + +For this chapter we're going to use a very simple ordering system as our +example. It is a somewhat contrived example because of its extreme +simplicity, but it serves to demonstrate the very basics of setting up +and using JMS. + +We will have a single JMS Queue called `OrderQueue`, and we will have a +single `MessageProducer` sending an order message to the queue and a +single `MessageConsumer` consuming the order message from the queue. + +The queue will be a `durable` queue, i.e. it will survive a server +restart or crash. We also want to pre-deploy the queue, i.e. specify the +queue in the server JMS configuration so it is created automatically +without us having to explicitly create it from the client. + +JNDI Configuration +================== + +The JMS specification establishes the convention that *administered +objects* (i.e. JMS queue, topic and connection factory instances) are +made available via the JNDI API. Brokers are free to implement JNDI as +they see fit assuming the implementation fits the API. ActiveMQ does not +have a JNDI server. Rather, it uses a client-side JNDI implementation +that relies on special properties set in the environment to construct +the appropriate JMS objects. In other words, no objects are stored in +JNDI on the ActiveMQ server. There are simply instantiated on the client +based on the provided configuration. Let's look at the different kinds +of administered objects and how to configure them. + +> **Note** +> +> The following configuration properties *are strictly required when +> ActiveMQ is running in stand-alone mode*. When ActiveMQ is integrated +> to an application server (e.g. Wildfly) the application server itself +> will almost certainly provide a JNDI client with its own properties. + +ConnectionFactory JNDI +---------------------- + +A JMS connection factory is used by the client to make connections to +the server. It knows the location of the server it is connecting to, as +well as many other configuration parameters. + +By default, a `javax.naming.Context` instance created using the +`org.apache.activemq.jndi.ActiveMQInitialContextFactory` will +automatically have the following connection factories available for +lookup: + +- `ConnectionFactory` + +- `XAConnectionFactory` + +- `QueueConnectionFactory` + +- `TopicConnectionFactory` + +Here's a simple example of the JNDI context environment for a client +looking up a connection factory to access an *embedded* instance of +ActiveMQ: + + java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory + +It's really as simple as that. As noted previously, any JNDI context +created with the `ActiveMQInitialContextFactory` will have a set of +default connection factories available. Therefore, only the +`java.naming.factory.initial` property is required to access an embedded +broker. + +In certain situations there could be multiple server instances running +within a particular JVM. In that situation each server would typically +have an InVM acceptor with a unique server-ID. A client using JMS and +JNDI can account for this by specifying a +`javax.naming.Context.PROVIDER_URL` (`String` value of +"java.naming.provider.url") in the JNDI environment like `vm://2` where +`2` is the server-ID for acceptor. + +Here is a list of all the supported URL schemes: + +- `vm` + +- `tcp` + +- `udp` + +- `jgroups` + +Most clients won't be connecting to an embedded broker. Clients will +most commonly connect across a network a remote broker. In that case the +client can use the `javax.naming.Context.PROVIDER_URL` (`String` value +of "java.naming.provider.url") in the JNDI environment to specify where +to connect. Here's a simple example of a client configuring a connection +factory to connect to a remote broker running on myhost:5445: + + java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory + java.naming.provider.url=tcp://myhost:5445 + +In the example above the client is using the `tcp` scheme for the +provider URL. A client may also specify multiple comma-delimited +host:port combinations in the URL (e.g. +`tcp://remote-host1:5445,remote-host2:5445`). Whether there is one or +many host:port combinations in the URL they are treated as the *initial +connector(s)* for the underlying connection. + +The `udp` scheme is also supported which should use an host:port +combination that matches the `group-address` and `group-port` from the +corresponding `broadcast-group` configured on the ActiveMQ server(s). + +Each scheme has a specific set of properties which can be set using the +traditional URL query string format (e.g. +`scheme://host:port?key1=value1&key2=value2`) to customize the +underlying transport mechanism. For example, if a client wanted to +connect to a remote server using TCP and SSL it would use a +`Context.PROVIDER_URL` of `tcp://remote-host:5445?ssl-enabled=true`. + +All the properties available for the `tcp` scheme are described in [the +documentation regarding the Netty +transport](#configuring-transports.netty). + +The `udp` scheme supports 4 properties: + +- `local-address` - If you are running with multiple network + interfaces on the same machine, you may want to specify that the + discovery group listens only only a specific interface. To do this + you can specify the interface address with this parameter. + +- `local-port` - If you want to specify a local port to which the + datagram socket is bound you can specify it here. Normally you would + just use the default value of -1 which signifies that an anonymous + port should be used. This parameter is always specified in + conjunction with `local-address`. + +- `refresh-timeout` - This is the period the discovery group waits + after receiving the last broadcast from a particular server before + removing that servers connector pair entry from its list. You would + normally set this to a value significantly higher than the + broadcast-period on the broadcast group otherwise servers might + intermittently disappear from the list even though they are still + broadcasting due to slight differences in timing. This parameter is + optional, the default value is 10000 milliseconds (10 seconds). + +- `discovery-initial-wait-timeout` - If the connection factory is used + immediately after creation then it may not have had enough time to + received broadcasts from all the nodes in the cluster. On first + usage, the connection factory will make sure it waits this long + since creation before creating the first connection. The default + value for this parameter is 10000 milliseconds. + +Lastly, the `jgroups` scheme is supported which provides an alternative +to the `udp` scheme for server discovery. The URL pattern is as follows +`jgroups://<jgroups-xml-conf-filename>` where +`<jgroups-xml-conf-filename>` refers to an XML file on the classpath +that contains the JGroups configuration. + +The `refresh-timeout` and `discovery-initial-wait-timeout` properties +are supported just like with `udp`. + +Although a `javax.naming.Context` instance created using the +`org.apache.activemq.jndi.ActiveMQInitialContextFactory` will +automatically have some connection factories present, it is possible for +a client to specify its own connection factories. This is done using the +`org.apache.activemq.jndi.ActiveMQInitialContextFactory.CONNECTION_FACTORY_NAMES` +property (String value of "connectionFactoryNames"). The value for this +property is a comma delimited String of all the connection factories the +client wishes to create. For example: + + java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory + java.naming.provider.url=tcp://localhost:5445 + connectionFactoryNames=myConnectionFactory + +In this example, the client is creating a connection factory named +"myConnectionFactory." This replaces all the default connection +factories so that only the "myConnectionFactory" connection factory is +available to the client. + +Aside from the underlying transport, the underlying connection factory +implementation can also be configured using special properties. To +configure a particular connection factory the client would follow this +pattern for the property name to set in the environment: +`connection.<connection-factory-name>.<property-name>`. For example, if +the client wanted to customize the default connection factory +"ConnectionFactory" to support high-availability then it would do this: + + java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory + java.naming.provider.url=tcp://myhost:5445 + connection.ConnectionFactory.ha=true + +Any property available on the underlying +`org.apache.activemq.jms.client.ActiveMQConnectionFactory` can be set +this way in addition to the `ha` (boolean) and `type` (String) +properties. Here are the different options for the `type`: + + type interface + --------------- ------------------------------------ + CF (default) javax.jms.ConnectionFactory + XA\_CF javax.jms.XAConnectionFactory + QUEUE\_CF javax.jms.QueueConnectionFactory + QUEUE\_XA\_CF javax.jms.XAQueueConnectionFactory + TOPIC\_CF javax.jms.TopicConnectionFactory + TOPIC\_XA\_CF javax.jms.XATopicConnectionFactory + + : Configuration for Connection Factory Types + +Destination JNDI +---------------- + +JMS destinations are also typically looked up via JNDI. As with +connection factories, destinations can be configured using special +properties in the JNDI context environment. The property *name* should +follow the pattern: `queue.<jndi-binding>` or `topic.<jndi-binding>`. +The property *value* should be the name of the queue hosted by the +ActiveMQ server. For example, if the server had a JMS queue configured +like so: + + <queue name="OrderQueue"/> + +And if the client wanted to bind this queue to "queues/OrderQueue" then +the JNDI properties would be configured like so: + + java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory + java.naming.provider.url=tcp://myhost:5445 + queue.queues/OrderQueue=OrderQueue + +It is also possible to look-up JMS destinations which haven't been +configured explicitly in the JNDI context environment. This is possible +using `dynamicQueues/` or `dynamicTopics/` in the look-up string. For +example, if the client wanted to look-up the aforementioned "OrderQueue" +it could do so simply by using the string "dynamicQueues/OrderQueue". +Note, the text that follows `dynamicQueues/` or `dynamicTopics/` must +correspond *exactly* to the name of the destination on the server. + +The code +-------- + +Here's the code for the example: + +First we'll create a JNDI initial context from which to lookup our JMS +objects. If the above properties are set in `jndi.properties` and it is +on the classpath then any new, empty `InitialContext` will be +initialized using those properties: + + InitialContext ic = new InitialContext(); + +Now we'll look up the connection factory from which we can create +connections to myhost:5445: + + ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory"); + +And look up the Queue: + + Queue orderQueue = (Queue)ic.lookup("queues/OrderQueue"); + +Next we create a JMS connection using the connection factory: + + Connection connection = cf.createConnection(); + +And we create a non transacted JMS Session, with AUTO\_ACKNOWLEDGE +acknowledge mode: + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + +We create a MessageProducer that will send orders to the queue: + + MessageProducer producer = session.createProducer(orderQueue); + +And we create a MessageConsumer which will consume orders from the +queue: + + MessageConsumer consumer = session.createConsumer(orderQueue); + +We make sure we start the connection, or delivery won't occur on it: + + connection.start(); + +We create a simple TextMessage and send it: + + TextMessage message = session.createTextMessage("This is an order"); + producer.send(message); + +And we consume the message: + + TextMessage receivedMessage = (TextMessage)consumer.receive(); + System.out.println("Got order: " + receivedMessage.getText()); + +It is as simple as that. For a wide range of working JMS examples please +see the examples directory in the distribution. + +> **Warning** +> +> Please note that JMS connections, sessions, producers and consumers +> are *designed to be re-used*. +> +> It is an anti-pattern to create new connections, sessions, producers +> and consumers for each message you produce or consume. If you do this, +> your application will perform very poorly. This is discussed further +> in the section on performance tuning ?. + +Directly instantiating JMS Resources without using JNDI +======================================================= + +Although it is a very common JMS usage pattern to lookup JMS +*Administered Objects* (that's JMS Queue, Topic and ConnectionFactory +instances) from JNDI, in some cases you just think "Why do I need JNDI? +Why can't I just instantiate these objects directly?" + +With ActiveMQ you can do exactly that. ActiveMQ supports the direct +instantiation of JMS Queue, Topic and ConnectionFactory instances, so +you don't have to use JNDI at all. + +For a full working example of direct instantiation please see the JMS +examples in ?. + +Here's our simple example, rewritten to not use JNDI at all: + +We create the JMS ConnectionFactory object via the ActiveMQJMSClient +Utility class, note we need to provide connection parameters and specify +which transport we are using, for more information on connectors please +see ?. + + + TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class.getName()); + ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF,transportConfiguration); + +We also create the JMS Queue object via the ActiveMQJMSClient Utility +class: + + Queue orderQueue = ActiveMQJMSClient.createQueue("OrderQueue"); + +Next we create a JMS connection using the connection factory: + + Connection connection = cf.createConnection(); + +And we create a non transacted JMS Session, with AUTO\_ACKNOWLEDGE +acknowledge mode: + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + +We create a MessageProducer that will send orders to the queue: + + MessageProducer producer = session.createProducer(orderQueue); + +And we create a MessageConsumer which will consume orders from the +queue: + + MessageConsumer consumer = session.createConsumer(orderQueue); + +We make sure we start the connection, or delivery won't occur on it: + + connection.start(); + +We create a simple TextMessage and send it: + + TextMessage message = session.createTextMessage("This is an order"); + producer.send(message); + +And we consume the message: + + TextMessage receivedMessage = (TextMessage)consumer.receive(); + System.out.println("Got order: " + receivedMessage.getText()); + +Setting The Client ID +===================== + +This represents the client id for a JMS client and is needed for +creating durable subscriptions. It is possible to configure this on the +connection factory and can be set via the `client-id` element. Any +connection created by this connection factory will have this set as its +client id. + +Setting The Batch Size for DUPS\_OK +=================================== + +When the JMS acknowledge mode is set to `DUPS_OK` it is possible to +configure the consumer so that it sends acknowledgements in batches +rather that one at a time, saving valuable bandwidth. This can be +configured via the connection factory via the `dups-ok-batch-size` +element and is set in bytes. The default is 1024 \* 1024 bytes = 1 MiB. + +Setting The Transaction Batch Size +================================== + +When receiving messages in a transaction it is possible to configure the +consumer to send acknowledgements in batches rather than individually +saving valuable bandwidth. This can be configured on the connection +factory via the `transaction-batch-size` element and is set in bytes. +The default is 1024 \* 1024.
