http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/connection-ttl.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/connection-ttl.xml b/docs/user-manual/en/connection-ttl.xml deleted file mode 100644 index dceca73..0000000 --- a/docs/user-manual/en/connection-ttl.xml +++ /dev/null @@ -1,202 +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="connection-ttl"> - <title>Detecting Dead Connections</title> - <para>In this section we will discuss connection time-to-live (TTL) and explain how ActiveMQ - deals with crashed clients and clients which have exited without cleanly closing their - resources.</para> - <section id="dead.connections"> - <title>Cleaning up Dead Connection Resources on the Server</title> - <para>Before a ActiveMQ client application exits it is considered good practice that it - should close its resources in a controlled manner, using a <literal>finally</literal> - block.</para> - <para>Here's an example of a well behaved core client application closing its session and - session factory in a finally block:</para> - <programlisting> -ServerLocator locator = null; -ClientSessionFactory sf = null; -ClientSession session = null; - -try -{ - locator = ActiveMQClient.createServerLocatorWithoutHA(..); - - sf = locator.createClientSessionFactory();; - - session = sf.createSession(...); - - ... do some stuff with the session... -} -finally -{ - if (session != null) - { - session.close(); - } - - if (sf != null) - { - sf.close(); - } - - if(locator != null) - { - locator.close(); - } -}</programlisting> - <para>And here's an example of a well behaved JMS client application:</para> - <programlisting> -Connection jmsConnection = null; - -try -{ - ConnectionFactory jmsConnectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(...); - - jmsConnection = jmsConnectionFactory.createConnection(); - - ... do some stuff with the connection... -} -finally -{ - if (connection != null) - { - connection.close(); - } -}</programlisting> - <para>Unfortunately users don't always write well behaved applications, and sometimes - clients just crash so they don't have a chance to clean up their resources!</para> - <para>If this occurs then it can leave server side resources, like sessions, hanging on the - server. If these were not removed they would cause a resource leak on the server and - over time this result in the server running out of memory or other resources.</para> - <para>We have to balance the requirement for cleaning up dead client resources with the fact - that sometimes the network between the client and the server can fail and then come - back, allowing the client to reconnect. ActiveMQ supports client reconnection, so we - don't want to clean up "dead" server side resources too soon or this will prevent any - client from reconnecting, as it won't be able to find its old sessions on the - server.</para> - <para>ActiveMQ makes all of this configurable. For each <literal - >ClientSessionFactory</literal> we define a <emphasis>connection TTL</emphasis>. - Basically, the TTL determines how long the server will keep a connection alive in the - absence of any data arriving from the client. The client will automatically send "ping" - packets periodically to prevent the server from closing it down. If the server doesn't - receive any packets on a connection for the connection TTL time, then it will - automatically close all the sessions on the server that relate to that - connection.</para> - <para>If you're using JMS, the connection TTL is defined by the <literal - >ConnectionTTL</literal> attribute on a <literal>ActiveMQConnectionFactory</literal> - instance, or if you're deploying JMS connection factory instances direct into JNDI on - the server side, you can specify it in the xml config, using the parameter <literal - >connection-ttl</literal>.</para> - <para>The default value for connection ttl on an "unreliable" connection (e.g. a Netty - connection) is <literal>60000</literal>ms, i.e. 1 minute. The default value for connection - ttl on a "reliable" connection (e.g. an in-vm connection) is <literal>-1</literal>. A - value of <literal>-1</literal> for <literal>ConnectionTTL</literal> means the server - will never time out the connection on the server side.</para> - <para id="connection-ttl.override">If you do not wish clients to be able to specify their own connection TTL, you can - override all values used by a global value set on the server side. This can be done by - specifying the <literal>connection-ttl-override</literal> attribute in the server side - configuration. The default value for <literal>connection-ttl-override</literal> is - <literal>-1</literal> which means "do not override" (i.e. let clients use their own - values).</para> - <section> - <title>Closing core sessions or JMS connections that you have failed to close</title> - <para>As previously discussed, it's important that all core client sessions and JMS - connections are always closed explicitly in a <literal>finally</literal> block when - you are finished using them. </para> - <para>If you fail to do so, ActiveMQ will detect this at garbage collection time, and log - a warning similar to the following in the logs (If you are using JMS the warning - will involve a JMS connection not a client session):</para> - <programlisting> -[Finalizer] 20:14:43,244 WARNING [org.apache.activemq.core.client.impl.DelegatingSession] I'm closing a ClientSession you left open. Please make sure you close all ClientSessions explicitly before let -ting them go out of scope! -[Finalizer] 20:14:43,244 WARNING [org.apache.activemq.core.client.impl.DelegatingSession] The session you didn't close was created here: -java.lang.Exception - at org.apache.activemq.core.client.impl.DelegatingSession.<init>(DelegatingSession.java:83) - at org.acme.yourproject.YourClass (YourClass.java:666)</programlisting> - <para>ActiveMQ will then close the connection / client session for you.</para> - <para>Note that the log will also tell you the exact line of your user code where you - created the JMS connection / client session that you later did not close. This will - enable you to pinpoint the error in your code and correct it appropriately.</para> - </section> - </section> - <section> - <title>Detecting failure from the client side.</title> - <para>In the previous section we discussed how the client sends pings to the server and how - "dead" connection resources are cleaned up by the server. There's also another reason - for pinging, and that's for the <emphasis>client</emphasis> to be able to detect that - the server or network has failed.</para> - <para>As long as the client is receiving data from the server it will consider the - connection to be still alive. </para> - <para>If the client does not receive any packets for <literal - >client-failure-check-period</literal> milliseconds then it will consider the - connection failed and will either initiate failover, or call any <literal - >FailureListener</literal> instances (or <literal>ExceptionListener</literal> - instances if you are using JMS) depending on how it has been configured.</para> - <para>If you're using JMS it's defined by the <literal>ClientFailureCheckPeriod</literal> - attribute on a <literal>ActiveMQConnectionFactory</literal> instance, or if you're - deploying JMS connection factory instances direct into JNDI on the server side, you can - specify it in the <literal>activemq-jms.xml </literal> configuration file, using the - parameter <literal>client-failure-check-period</literal>.</para> - <para>The default value for client failure check period on an "unreliable" connection (e.g. - a Netty connection) is <literal>30000</literal>ms, i.e. 30 seconds. The default value - for client failure check period on a "reliable" connection (e.g. an in-vm connection) - is <literal>-1</literal>. A value of <literal>-1</literal> means the client will never fail the - connection on the client side if no data is received from the server. Typically this is - much lower than connection TTL to allow clients to reconnect in case of transitory - failure.</para> - </section> - <section id="connection-ttl.async-connection-execution"> - <title>Configuring Asynchronous Connection Execution</title> - <para>Most packets received on the server side are executed on the remoting thread. These packets - represent short-running operations and are always executed on the remoting thread for - performance reasons.</para> - <para>However, by default some kinds of packets are executed using a thread from a - thread pool so that the remoting thread is not tied up for too long. Please note that - processing operations asynchronously on another thread adds a little more latency. These packets - are:</para> - <itemizedlist> - <listitem> - <para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.RollbackMessage</literal></para> - </listitem> - <listitem> - <para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionCloseMessage</literal></para> - </listitem> - <listitem> - <para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionCommitMessage</literal></para> - </listitem> - <listitem> - <para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionXACommitMessage</literal></para> - </listitem> - <listitem> - <para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionXAPrepareMessage</literal></para> - </listitem> - <listitem> - <para><literal>org.apache.activemq.core.protocol.core.impl.wireformat.SessionXARollbackMessage</literal></para> - </listitem> - </itemizedlist> - <para>To disable asynchronous connection execution, set the parameter - <literal>async-connection-execution-enabled</literal> in - <literal>activemq-configuration.xml</literal> to <literal>false</literal> (default value is - <literal>true</literal>).</para> - </section> -</chapter>
http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/core-bridges.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/core-bridges.md b/docs/user-manual/en/core-bridges.md new file mode 100644 index 0000000..6b6b90f --- /dev/null +++ b/docs/user-manual/en/core-bridges.md @@ -0,0 +1,225 @@ +Core Bridges +============ + +The function of a bridge is to consume messages from a source queue, and +forward them to a target address, typically on a different ActiveMQ +server. + +The source and target servers do not have to be in the same cluster +which makes bridging suitable for reliably sending messages from one +cluster to another, for instance across a WAN, or internet and where the +connection may be unreliable. + +The bridge has built in resilience to failure so if the target server +connection is lost, e.g. due to network failure, the bridge will retry +connecting to the target until it comes back online. When it comes back +online it will resume operation as normal. + +In summary, bridges are a way to reliably connect two separate ActiveMQ +servers together. With a core bridge both source and target servers must +be ActiveMQ servers. + +Bridges can be configured to provide *once and only once* delivery +guarantees even in the event of the failure of the source or the target +server. They do this by using duplicate detection (described in ?). + +> **Note** +> +> Although they have similar function, don't confuse core bridges with +> JMS bridges! +> +> Core bridges are for linking a ActiveMQ node with another ActiveMQ +> node and do not use the JMS API. A JMS Bridge is used for linking any +> two JMS 1.1 compliant JMS providers. So, a JMS Bridge could be used +> for bridging to or from different JMS compliant messaging system. It's +> always preferable to use a core bridge if you can. Core bridges use +> duplicate detection to provide *once and only once* guarantees. To +> provide the same guarantee using a JMS bridge you would have to use XA +> which has a higher overhead and is more complex to configure. + +Configuring Bridges +=================== + +Bridges are configured in `activemq-configuration.xml`. Let's kick off +with an example (this is actually from the bridge example): + + <bridge name="my-bridge"> + <queue-name>jms.queue.sausage-factory</queue-name> + <forwarding-address>jms.queue.mincing-machine</forwarding-address> + <filter-string="name='aardvark'"/> + <transformer-class-name> + org.apache.activemq.jms.example.HatColourChangeTransformer + </transformer-class-name> + <retry-interval>1000</retry-interval> + <ha>true</ha> + <retry-interval-multiplier>1.0</retry-interval-multiplier> + <initial-connect-attempts>-1</initial-connect-attempts> + <reconnect-attempts>-1</reconnect-attempts> + <failover-on-server-shutdown>false</failover-on-server-shutdown> + <use-duplicate-detection>true</use-duplicate-detection> + <confirmation-window-size>10000000</confirmation-window-size> + <user>foouser</user> + <password>foopassword</password> + <static-connectors> + <connector-ref>remote-connector</connector-ref> + </static-connectors> + <!-- alternative to static-connectors + <discovery-group-ref discovery-group-name="bridge-discovery-group"/> + --> + </bridge> + +In the above example we have shown all the parameters its possible to +configure for a bridge. In practice you might use many of the defaults +so it won't be necessary to specify them all explicitly. + +Let's take a look at all the parameters in turn: + +- `name` attribute. All bridges must have a unique name in the server. + +- `queue-name`. This is the unique name of the local queue that the + bridge consumes from, it's a mandatory parameter. + + The queue must already exist by the time the bridge is instantiated + at start-up. + + > **Note** + > + > If you're using JMS then normally the JMS configuration + > `activemq-jms.xml` is loaded after the core configuration file + > `activemq-configuration.xml` is loaded. If your bridge is + > consuming from a JMS queue then you'll need to make sure the JMS + > queue is also deployed as a core queue in the core configuration. + > Take a look at the bridge example for an example of how this is + > done. + +- `forwarding-address`. This is the address on the target server that + the message will be forwarded to. If a forwarding address is not + specified, then the original address of the message will be + retained. + +- `filter-string`. An optional filter string can be supplied. If + specified then only messages which match the filter expression + specified in the filter string will be forwarded. The filter string + follows the ActiveMQ filter expression syntax described in ?. + +- `transformer-class-name`. An optional transformer-class-name can be + specified. This is the name of a user-defined class which implements + the `org.apache.activemq.core.server.cluster.Transformer` interface. + + If this is specified then the transformer's `transform()` method + will be invoked with the message before it is forwarded. This gives + you the opportunity to transform the message's header or body before + forwarding it. + +- `ha`. This optional parameter determines whether or not this bridge + should support high availability. True means it will connect to any + available server in a cluster and support failover. The default + value is `false`. + +- `retry-interval`. This optional parameter determines the period in + milliseconds between subsequent reconnection attempts, if the + connection to the target server has failed. The default value is + `2000`milliseconds. + +- `retry-interval-multiplier`. This optional parameter determines + determines a multiplier to apply to the time since the last retry to + compute the time to the next retry. + + This allows you to implement an *exponential backoff* between retry + attempts. + + Let's take an example: + + If we set `retry-interval`to `1000` ms and we set + `retry-interval-multiplier` to `2.0`, then, if the first reconnect + attempt fails, we will wait `1000` ms then `2000` ms then `4000` ms + between subsequent reconnection attempts. + + The default value is `1.0` meaning each reconnect attempt is spaced + at equal intervals. + +- `initial-connect-attempts`. This optional parameter determines the + total number of initial connect attempts the bridge will make before + giving up and shutting down. A value of `-1` signifies an unlimited + number of attempts. The default value is `-1`. + +- `reconnect-attempts`. This optional parameter determines the total + number of reconnect attempts the bridge will make before giving up + and shutting down. A value of `-1` signifies an unlimited number of + attempts. The default value is `-1`. + +- `failover-on-server-shutdown`. This optional parameter determines + whether the bridge will attempt to failover onto a backup server (if + specified) when the target server is cleanly shutdown rather than + crashed. + + The bridge connector can specify both a live and a backup server, if + it specifies a backup server and this parameter is set to `true` + then if the target server is *cleanly* shutdown the bridge + connection will attempt to failover onto its backup. If the bridge + connector has no backup server configured then this parameter has no + effect. + + Sometimes you want a bridge configured with a live and a backup + target server, but you don't want to failover to the backup if the + live server is simply taken down temporarily for maintenance, this + is when this parameter comes in handy. + + The default value for this parameter is `false`. + +- `use-duplicate-detection`. This optional parameter determines + whether the bridge will automatically insert a duplicate id property + into each message that it forwards. + + Doing so, allows the target server to perform duplicate detection on + messages it receives from the source server. If the connection fails + or server crashes, then, when the bridge resumes it will resend + unacknowledged messages. This might result in duplicate messages + being sent to the target server. By enabling duplicate detection + allows these duplicates to be screened out and ignored. + + This allows the bridge to provide a *once and only once* delivery + guarantee without using heavyweight methods such as XA (see ? for + more information). + + The default value for this parameter is `true`. + +- `confirmation-window-size`. This optional parameter determines the + `confirmation-window-size` to use for the connection used to forward + messages to the target node. This attribute is described in section + ? + + > **Warning** + > + > When using the bridge to forward messages to an address which uses + > the `BLOCK` `address-full-policy` from a queue which has a + > `max-size-bytes` set it's important that + > `confirmation-window-size` is less than or equal to + > `max-size-bytes` to prevent the flow of messages from ceasing. + +- `user`. This optional parameter determines the user name to use when + creating the bridge connection to the remote server. If it is not + specified the default cluster user specified by `cluster-user` in + `activemq-configuration.xml` will be used. + +- `password`. This optional parameter determines the password to use + when creating the bridge connection to the remote server. If it is + not specified the default cluster password specified by + `cluster-password` in `activemq-configuration.xml` will be used. + +- `static-connectors` or `discovery-group-ref`. Pick either of these + options to connect the bridge to the target server. + + The `static-connectors` is a list of `connector-ref` elements + pointing to `connector` elements defined elsewhere. A *connector* + encapsulates knowledge of what transport to use (TCP, SSL, HTTP etc) + as well as the server connection parameters (host, port etc). For + more information about what connectors are and how to configure + them, please see ?. + + The `discovery-group-ref` element has one attribute - + `discovery-group-name`. This attribute points to a `discovery-group` + defined elsewhere. For more information about what discovery-groups + are and how to configure them, please see ?. + + http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/core-bridges.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/core-bridges.xml b/docs/user-manual/en/core-bridges.xml deleted file mode 100644 index 2276a2e..0000000 --- a/docs/user-manual/en/core-bridges.xml +++ /dev/null @@ -1,241 +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="core-bridges"> - <title>Core Bridges</title> - <para>The function of a bridge is to consume messages from a source queue, and forward them to a - target address, typically on a different ActiveMQ server.</para> - <para>The source and target servers do not have to be in the same cluster which makes bridging - suitable for reliably sending messages from one cluster to another, for instance across a - WAN, or internet and where the connection may be unreliable.</para> - <para>The bridge has built in resilience to failure so if the target server connection is lost, - e.g. due to network failure, the bridge will retry connecting to the target until it comes - back online. When it comes back online it will resume operation as normal.</para> - <para>In summary, bridges are a way to reliably connect two separate ActiveMQ servers together. - With a core bridge both source and target servers must be ActiveMQ servers.</para> - <para>Bridges can be configured to provide <emphasis>once and only once</emphasis> delivery - guarantees even in the event of the failure of the source or the target server. They do this - by using duplicate detection (described in <xref linkend="duplicate-detection"/>).</para> - <note> - <para>Although they have similar function, don't confuse core bridges with JMS - bridges!</para> - <para>Core bridges are for linking a ActiveMQ node with another ActiveMQ node and do not use - the JMS API. A JMS Bridge is used for linking any two JMS 1.1 compliant JMS providers. - So, a JMS Bridge could be used for bridging to or from different JMS compliant messaging - system. It's always preferable to use a core bridge if you can. Core bridges use - duplicate detection to provide <emphasis>once and only once</emphasis> guarantees. To - provide the same guarantee using a JMS bridge you would have to use XA which has a - higher overhead and is more complex to configure.</para> - </note> - <section> - <title>Configuring Bridges</title> - <para>Bridges are configured in <literal>activemq-configuration.xml</literal>. Let's kick off - with an example (this is actually from the bridge example):</para> - <programlisting> -<bridge name="my-bridge"> - <queue-name>jms.queue.sausage-factory</queue-name> - <forwarding-address>jms.queue.mincing-machine</forwarding-address> - <filter-string="name='aardvark'"/> - <transformer-class-name> - org.apache.activemq.jms.example.HatColourChangeTransformer - </transformer-class-name> - <retry-interval>1000</retry-interval> - <ha>true</ha> - <retry-interval-multiplier>1.0</retry-interval-multiplier> - <initial-connect-attempts>-1</initial-connect-attempts> - <reconnect-attempts>-1</reconnect-attempts> - <failover-on-server-shutdown>false</failover-on-server-shutdown> - <use-duplicate-detection>true</use-duplicate-detection> - <confirmation-window-size>10000000</confirmation-window-size> - <user>foouser</user> - <password>foopassword</password> - <static-connectors> - <connector-ref>remote-connector</connector-ref> - </static-connectors> - <!-- alternative to static-connectors - <discovery-group-ref discovery-group-name="bridge-discovery-group"/> - --> -</bridge></programlisting> - <para>In the above example we have shown all the parameters its possible to configure for a - bridge. In practice you might use many of the defaults so it won't be necessary to - specify them all explicitly.</para> - <para>Let's take a look at all the parameters in turn:</para> - <itemizedlist> - <listitem> - <para><literal>name</literal> attribute. All bridges must have a unique name in the - server.</para> - </listitem> - <listitem> - <para><literal>queue-name</literal>. This is the unique name of the local queue that - the bridge consumes from, it's a mandatory parameter.</para> - <para>The queue must already exist by the time the bridge is instantiated at - start-up.</para> - <note> - <para>If you're using JMS then normally the JMS configuration <literal - >activemq-jms.xml</literal> is loaded after the core configuration file - <literal>activemq-configuration.xml</literal> is loaded. If your bridge - is consuming from a JMS queue then you'll need to make sure the JMS queue is - also deployed as a core queue in the core configuration. Take a look at the - bridge example for an example of how this is done.</para> - </note> - </listitem> - <listitem> - <para><literal>forwarding-address</literal>. This is the address on the target - server that the message will be forwarded to. If a forwarding address is not - specified, then the original address of the message will be retained.</para> - </listitem> - <listitem> - <para><literal>filter-string</literal>. An optional filter string can be supplied. - If specified then only messages which match the filter expression specified in - the filter string will be forwarded. The filter string follows the ActiveMQ - filter expression syntax described in <xref linkend="filter-expressions" - />.</para> - </listitem> - <listitem> - <para><literal>transformer-class-name</literal>. An optional transformer-class-name - can be specified. This is the name of a user-defined class which implements the - <literal>org.apache.activemq.core.server.cluster.Transformer</literal> - interface.</para> - <para>If this is specified then the transformer's <literal>transform()</literal> - method will be invoked with the message before it is forwarded. This gives you - the opportunity to transform the message's header or body before forwarding - it.</para> - </listitem> - <listitem> - <para><literal>ha</literal>. This optional parameter determines whether or not this - bridge should support high availability. True means it will connect to any available - server in a cluster and support failover. The default value is <literal - >false</literal>.</para> - </listitem> - <listitem> - <para><literal>retry-interval</literal>. This optional parameter determines the - period in milliseconds between subsequent reconnection attempts, if the - connection to the target server has failed. The default value is <literal - >2000</literal>milliseconds.</para> - </listitem> - <listitem> - <para><literal>retry-interval-multiplier</literal>. This optional parameter - determines determines a multiplier to apply to the time since the last retry to - compute the time to the next retry.</para> - <para>This allows you to implement an <emphasis>exponential backoff</emphasis> - between retry attempts.</para> - <para>Let's take an example:</para> - <para>If we set <literal>retry-interval</literal>to <literal>1000</literal> ms and - we set <literal>retry-interval-multiplier</literal> to <literal>2.0</literal>, - then, if the first reconnect attempt fails, we will wait <literal>1000</literal> - ms then <literal>2000</literal> ms then <literal>4000</literal> ms between - subsequent reconnection attempts.</para> - <para>The default value is <literal>1.0</literal> meaning each reconnect attempt is - spaced at equal intervals.</para> - </listitem> - <listitem> - <para><literal>initial-connect-attempts</literal>. This optional parameter determines the - total number of initial connect attempts the bridge will make before giving up and - shutting down. A value of <literal>-1</literal> signifies an unlimited number of - attempts. The default value is <literal>-1</literal>.</para> - </listitem> - <listitem> - <para><literal>reconnect-attempts</literal>. This optional parameter determines the - total number of reconnect attempts the bridge will make before giving up and - shutting down. A value of <literal>-1</literal> signifies an unlimited number of - attempts. The default value is <literal>-1</literal>.</para> - </listitem> - <listitem> - <para><literal>failover-on-server-shutdown</literal>. This optional parameter - determines whether the bridge will attempt to failover onto a backup server (if - specified) when the target server is cleanly shutdown rather than - crashed.</para> - <para>The bridge connector can specify both a live and a backup server, if it - specifies a backup server and this parameter is set to <literal>true</literal> - then if the target server is <emphasis>cleanly</emphasis> shutdown the bridge - connection will attempt to failover onto its backup. If the bridge connector has - no backup server configured then this parameter has no effect. </para> - <para>Sometimes you want a bridge configured with a live and a backup target server, - but you don't want to failover to the backup if the live server is simply taken - down temporarily for maintenance, this is when this parameter comes in - handy.</para> - <para>The default value for this parameter is <literal>false</literal>.</para> - </listitem> - <listitem> - <para><literal>use-duplicate-detection</literal>. This optional parameter determines - whether the bridge will automatically insert a duplicate id property into each - message that it forwards.</para> - <para>Doing so, allows the target server to perform duplicate detection on messages - it receives from the source server. If the connection fails or server crashes, - then, when the bridge resumes it will resend unacknowledged messages. This might - result in duplicate messages being sent to the target server. By enabling - duplicate detection allows these duplicates to be screened out and - ignored.</para> - <para>This allows the bridge to provide a <emphasis>once and only once</emphasis> - delivery guarantee without using heavyweight methods such as XA (see <xref - linkend="duplicate-detection"/> for more information).</para> - <para>The default value for this parameter is <literal>true</literal>.</para> - </listitem> - <listitem> - <para><literal>confirmation-window-size</literal>. This optional parameter - determines the <literal>confirmation-window-size</literal> to use for the - connection used to forward messages to the target node. This attribute is - described in section <xref linkend="client-reconnection"/></para> - - <warning><para>When using the bridge to forward messages to an address which uses - the <literal>BLOCK</literal> <literal>address-full-policy</literal> from a - queue which has a <literal>max-size-bytes</literal> set it's important that - <literal>confirmation-window-size</literal> is less than or equal to - <literal>max-size-bytes</literal> to prevent the flow of messages from - ceasing.</para> - </warning> - - </listitem> - <listitem> - <para><literal>user</literal>. This optional parameter determines the user name to - use when creating the bridge connection to the remote server. If it is not - specified the default cluster user specified by <literal>cluster-user</literal> - in <literal>activemq-configuration.xml</literal> will be used. </para> - </listitem> - <listitem> - <para><literal>password</literal>. This optional parameter determines the password - to use when creating the bridge connection to the remote server. If it is not - specified the default cluster password specified by <literal - >cluster-password</literal> in <literal>activemq-configuration.xml</literal> - will be used. </para> - </listitem> - <listitem> - <para><literal>static-connectors</literal> or <literal>discovery-group-ref</literal>. - Pick either of these options to connect the bridge to the target server. - </para> - <para> The <literal>static-connectors</literal> is a list of <literal>connector-ref</literal> - elements pointing to <literal>connector</literal> elements defined elsewhere. - A <emphasis>connector</emphasis> encapsulates knowledge of what transport to - use (TCP, SSL, HTTP etc) as well as the server connection parameters (host, port - etc). For more information about what connectors are and how to configure them, - please see <xref linkend="configuring-transports"/>. - </para> - <para>The <literal>discovery-group-ref</literal> element has one attribute - - <literal>discovery-group-name</literal>. This attribute points to a - <literal>discovery-group</literal> defined elsewhere. For more information about - what discovery-groups are and how to configure them, please see - <xref linkend="clusters.discovery-groups"/>. - </para> - </listitem> - </itemizedlist> - </section> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/diverts.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/diverts.md b/docs/user-manual/en/diverts.md new file mode 100644 index 0000000..60b00f7 --- /dev/null +++ b/docs/user-manual/en/diverts.md @@ -0,0 +1,114 @@ +Diverting and Splitting Message Flows +===================================== + +ActiveMQ allows you to configure objects called *diverts* with some +simple server configuration. + +Diverts allow you to transparently divert messages routed to one address +to some other address, without making any changes to any client +application logic. + +Diverts can be *exclusive*, meaning that the message is diverted to the +new address, and does not go to the old address at all, or they can be +*non-exclusive* which means the message continues to go the old address, +and a *copy* of it is also sent to the new address. Non-exclusive +diverts can therefore be used for *splitting* message flows, e.g. there +may be a requirement to monitor every order sent to an order queue. + +Diverts can also be configured to have an optional message filter. If +specified then only messages that match the filter will be diverted. + +Diverts can also be configured to apply a `Transformer`. If specified, +all diverted messages will have the opportunity of being transformed by +the `Transformer`. + +A divert will only divert a message to an address on the *same server*, +however, if you want to divert to an address on a different server, a +common pattern would be to divert to a local store-and-forward queue, +then set up a bridge which consumes from that queue and forwards to an +address on a different server. + +Diverts are therefore a very sophisticated concept, which when combined +with bridges can be used to create interesting and complex routings. The +set of diverts on a server can be thought of as a type of routing table +for messages. Combining diverts with bridges allows you to create a +distributed network of reliable routing connections between multiple +geographically distributed servers, creating your global messaging mesh. + +Diverts are defined as xml in the `activemq-configuration.xml` file. +There can be zero or more diverts in the file. + +Please see ? for a full working example showing you how to configure and +use diverts. + +Let's take a look at some divert examples: + +Exclusive Divert +================ + +Let's take a look at an exclusive divert. An exclusive divert diverts +all matching messages that are routed to the old address to the new +address. Matching messages do not get routed to the old address. + +Here's some example xml configuration for an exclusive divert, it's +taken from the divert example: + + <divert name="prices-divert"> + <address>jms.topic.priceUpdates</address> + <forwarding-address>jms.queue.priceForwarding</forwarding-address> + <filter string="office='New York'"/> + <transformer-class-name> + org.apache.activemq.jms.example.AddForwardingTimeTransformer + </transformer-class-name> + <exclusive>true</exclusive> + </divert> + +We define a divert called '`prices-divert`' that will divert any +messages sent to the address '`jms.topic.priceUpdates`' (this +corresponds to any messages sent to a JMS Topic called '`priceUpdates`') +to another local address '`jms.queue.priceForwarding`' (this corresponds +to a local JMS queue called '`priceForwarding`' + +We also specify a message filter string so only messages with the +message property `office` with value `New York` will get diverted, all +other messages will continue to be routed to the normal address. The +filter string is optional, if not specified then all messages will be +considered matched. + +In this example a transformer class is specified. Again this is +optional, and if specified the transformer will be executed for each +matching message. This allows you to change the messages body or +properties before it is diverted. In this example the transformer simply +adds a header that records the time the divert happened. + +This example is actually diverting messages to a local store and forward +queue, which is configured with a bridge which forwards the message to +an address on another ActiveMQ server. Please see the example for more +details. + +Non-exclusive Divert +==================== + +Now we'll take a look at a non-exclusive divert. Non exclusive diverts +are the same as exclusive diverts, but they only forward a *copy* of the +message to the new address. The original message continues to the old +address + +You can therefore think of non-exclusive diverts as *splitting* a +message flow. + +Non exclusive diverts can be configured in the same way as exclusive +diverts with an optional filter and transformer, here's an example +non-exclusive divert, again from the divert example: + + <divert name="order-divert"> + <address>jms.queue.orders</address> + <forwarding-address>jms.topic.spyTopic</forwarding-address> + <exclusive>false</exclusive> + </divert> + +The above divert example takes a copy of every message sent to the +address '`jms.queue.orders`' (Which corresponds to a JMS Queue called +'`orders`') and sends it to a local address called +'`jms.topic.SpyTopic`' (which corresponds to a JMS Topic called +'`SpyTopic`'). http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/diverts.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/diverts.xml b/docs/user-manual/en/diverts.xml deleted file mode 100644 index b83c5c5..0000000 --- a/docs/user-manual/en/diverts.xml +++ /dev/null @@ -1,113 +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="diverts"> - <title>Diverting and Splitting Message Flows</title> - <para>ActiveMQ allows you to configure objects called <emphasis>diverts</emphasis> with - some simple server configuration.</para> - <para>Diverts allow you to transparently divert messages routed to one address to some other - address, without making any changes to any client application logic.</para> - <para>Diverts can be <emphasis>exclusive</emphasis>, meaning that the message is diverted - to the new address, and does not go to the old address at all, or they can be - <emphasis>non-exclusive</emphasis> which means the message continues to go the old - address, and a <emphasis>copy</emphasis> of it is also sent to the new address. - Non-exclusive diverts can therefore be used for <emphasis>splitting</emphasis> message - flows, e.g. there may be a requirement to monitor every order sent to an order queue.</para> - <para>Diverts can also be configured to have an optional message filter. If specified then only - messages that match the filter will be diverted.</para> - <para>Diverts can also be configured to apply a <literal>Transformer</literal>. If specified, - all diverted messages will have the opportunity of being transformed by the <literal - >Transformer</literal>.</para> - <para>A divert will only divert a message to an address on the <emphasis>same server</emphasis>, - however, if you want to divert to an address on a different server, a common pattern would - be to divert to a local store-and-forward queue, then set up a bridge which consumes from - that queue and forwards to an address on a different server.</para> - <para>Diverts are therefore a very sophisticated concept, which when combined with bridges can - be used to create interesting and complex routings. The set of diverts on a server can be - thought of as a type of routing table for messages. Combining diverts with bridges allows - you to create a distributed network of reliable routing connections between multiple - geographically distributed servers, creating your global messaging mesh.</para> - <para>Diverts are defined as xml in the <literal>activemq-configuration.xml</literal> file. There can - be zero or more diverts in the file.</para> - <para>Please see <xref linkend="divert-example" /> for a full working - example showing you how to configure and use diverts.</para> - <para>Let's take a look at some divert examples:</para> - <section> - <title>Exclusive Divert</title> - <para>Let's take a look at an exclusive divert. An exclusive divert diverts all matching - messages that are routed to the old address to the new address. Matching messages do not - get routed to the old address.</para> - <para>Here's some example xml configuration for an exclusive divert, it's taken from the - divert example:</para> - <programlisting> -<divert name="prices-divert"> - <address>jms.topic.priceUpdates</address> - <forwarding-address>jms.queue.priceForwarding</forwarding-address> - <filter string="office='New York'"/> - <transformer-class-name> - org.apache.activemq.jms.example.AddForwardingTimeTransformer - </transformer-class-name> - <exclusive>true</exclusive> -</divert></programlisting> - <para>We define a divert called '<literal>prices-divert</literal>' that will divert any - messages sent to the address '<literal>jms.topic.priceUpdates</literal>' (this - corresponds to any messages sent to a JMS Topic called '<literal - >priceUpdates</literal>') to another local address '<literal - >jms.queue.priceForwarding</literal>' (this corresponds to a local JMS queue called - '<literal>priceForwarding</literal>'</para> - <para>We also specify a message filter string so only messages with the message property - <literal>office</literal> with value <literal>New York</literal> will get diverted, - all other messages will continue to be routed to the normal address. The filter string - is optional, if not specified then all messages will be considered matched.</para> - <para>In this example a transformer class is specified. Again this is optional, and if - specified the transformer will be executed for each matching message. This allows you to - change the messages body or properties before it is diverted. In this example the - transformer simply adds a header that records the time the divert happened.</para> - <para>This example is actually diverting messages to a local store and forward queue, which - is configured with a bridge which forwards the message to an address on another ActiveMQ - server. Please see the example for more details.</para> - </section> - <section> - <title>Non-exclusive Divert</title> - <para>Now we'll take a look at a non-exclusive divert. Non exclusive diverts are the same as - exclusive diverts, but they only forward a <emphasis>copy</emphasis> of the message to - the new address. The original message continues to the old address</para> - <para>You can therefore think of non-exclusive diverts as <emphasis>splitting</emphasis> a - message flow.</para> - <para>Non exclusive diverts can be configured in the same way as exclusive diverts with an - optional filter and transformer, here's an example non-exclusive divert, again from the - divert example:</para> - <programlisting> -<divert name="order-divert"> - <address>jms.queue.orders</address> - <forwarding-address>jms.topic.spyTopic</forwarding-address> - <exclusive>false</exclusive> -</divert></programlisting> - <para>The above divert example takes a copy of every message sent to the address '<literal - >jms.queue.orders</literal>' (Which corresponds to a JMS Queue called '<literal - >orders</literal>') and sends it to a local address called '<literal - >jms.topic.SpyTopic</literal>' (which corresponds to a JMS Topic called '<literal - >SpyTopic</literal>').</para> - </section> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/duplicate-detection.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/duplicate-detection.md b/docs/user-manual/en/duplicate-detection.md new file mode 100644 index 0000000..b7776eb --- /dev/null +++ b/docs/user-manual/en/duplicate-detection.md @@ -0,0 +1,161 @@ +Duplicate Message Detection +=========================== + +ActiveMQ includes powerful automatic duplicate message detection, +filtering out duplicate messages without you having to code your own +fiddly duplicate detection logic at the application level. This chapter +will explain what duplicate detection is, how ActiveMQ uses it and how +and where to configure it. + +When sending messages from a client to a server, or indeed from a server +to another server, if the target server or connection fails sometime +after sending the message, but before the sender receives a response +that the send (or commit) was processed successfully then the sender +cannot know for sure if the message was sent successfully to the +address. + +If the target server or connection failed after the send was received +and processed but before the response was sent back then the message +will have been sent to the address successfully, but if the target +server or connection failed before the send was received and finished +processing then it will not have been sent to the address successfully. +From the senders point of view it's not possible to distinguish these +two cases. + +When the server recovers this leaves the client in a difficult +situation. It knows the target server failed, but it does not know if +the last message reached its destination ok. If it decides to resend the +last message, then that could result in a duplicate message being sent +to the address. If each message was an order or a trade then this could +result in the order being fulfilled twice or the trade being double +booked. This is clearly not a desirable situation. + +Sending the message(s) in a transaction does not help out either. If the +server or connection fails while the transaction commit is being +processed it is also indeterminate whether the transaction was +successfully committed or not! + +To solve these issues ActiveMQ provides automatic duplicate messages +detection for messages sent to addresses. + +Using Duplicate Detection for Message Sending +============================================= + +Enabling duplicate message detection for sent messages is simple: you +just need to set a special property on the message to a unique value. +You can create the value however you like, as long as it is unique. When +the target server receives the message it will check if that property is +set, if it is, then it will check in its in memory cache if it has +already received a message with that value of the header. If it has +received a message with the same value before then it will ignore the +message. + +> **Note** +> +> Using duplicate detection to move messages between nodes can give you +> the same *once and only once* delivery guarantees as if you were using +> an XA transaction to consume messages from source and send them to the +> target, but with less overhead and much easier configuration than +> using XA. + +If you're sending messages in a transaction then you don't have to set +the property for *every* message you send in that transaction, you only +need to set it once in the transaction. If the server detects a +duplicate message for any message in the transaction, then it will +ignore the entire transaction. + +The name of the property that you set is given by the value of +`org.apache.activemq.api.core.Message.HDR_DUPLICATE_DETECTION_ID`, which +is `_HQ_DUPL_ID` + +The value of the property can be of type `byte[]` or `SimpleString` if +you're using the core API. If you're using JMS it must be a `String`, +and its value should be unique. An easy way of generating a unique id is +by generating a UUID. + +Here's an example of setting the property using the core API: + + ... + + ClientMessage message = session.createMessage(true); + + SimpleString myUniqueID = "This is my unique id"; // Could use a UUID for this + + message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, myUniqueID); + + ... + +And here's an example using the JMS API: + + ... + + Message jmsMessage = session.createMessage(); + + String myUniqueID = "This is my unique id"; // Could use a UUID for this + + message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID); + + ... + +Configuring the Duplicate ID Cache +================================== + +The server maintains caches of received values of the +`org.apache.activemq.core.message.impl.HDR_DUPLICATE_DETECTION_ID` +property sent to each address. Each address has its own distinct cache. + +The cache is a circular fixed size cache. If the cache has a maximum +size of `n` elements, then the `n + 1`th id stored will overwrite the +`0`th element in the cache. + +The maximum size of the cache is configured by the parameter +`id-cache-size` in `activemq-configuration.xml`, the default value is +`2000` elements. + +The caches can also be configured to persist to disk or not. This is +configured by the parameter `persist-id-cache`, also in +`activemq-configuration.xml`. If this is set to `true` then each id will +be persisted to permanent storage as they are received. The default +value for this parameter is `true`. + +> **Note** +> +> When choosing a size of the duplicate id cache be sure to set it to a +> larger enough size so if you resend messages all the previously sent +> ones are in the cache not having been overwritten. + +Duplicate Detection and Bridges +=============================== + +Core bridges can be configured to automatically add a unique duplicate +id value (if there isn't already one in the message) before forwarding +the message to it's target. This ensures that if the target server +crashes or the connection is interrupted and the bridge resends the +message, then if it has already been received by the target server, it +will be ignored. + +To configure a core bridge to add the duplicate id header, simply set +the `use-duplicate-detection` to `true` when configuring a bridge in +`activemq-configuration.xml`. + +The default value for this parameter is `true`. + +For more information on core bridges and how to configure them, please +see ?. + +Duplicate Detection and Cluster Connections +=========================================== + +Cluster connections internally use core bridges to move messages +reliable between nodes of the cluster. Consequently they can also be +configured to insert the duplicate id header for each message they move +using their internal bridges. + +To configure a cluster connection to add the duplicate id header, simply +set the `use-duplicate-detection` to `true` when configuring a cluster +connection in `activemq-configuration.xml`. + +The default value for this parameter is `true`. + +For more information on cluster connections and how to configure them, +please see ?. http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/duplicate-detection.xml ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/duplicate-detection.xml b/docs/user-manual/en/duplicate-detection.xml deleted file mode 100644 index 605107a..0000000 --- a/docs/user-manual/en/duplicate-detection.xml +++ /dev/null @@ -1,148 +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="duplicate-detection"> - <title>Duplicate Message Detection</title> - <para>ActiveMQ includes powerful automatic duplicate message detection, filtering out - duplicate messages without you having to code your own fiddly duplicate detection logic at - the application level. This chapter will explain what duplicate detection is, how ActiveMQ - uses it and how and where to configure it.</para> - <para>When sending messages from a client to a server, or indeed from a server to another - server, if the target server or connection fails sometime after sending the message, but - before the sender receives a response that the send (or commit) was processed successfully - then the sender cannot know for sure if the message was sent successfully to the - address.</para> - <para>If the target server or connection failed after the send was received and processed but - before the response was sent back then the message will have been sent to the address - successfully, but if the target server or connection failed before the send was received and - finished processing then it will not have been sent to the address successfully. From the - senders point of view it's not possible to distinguish these two cases.</para> - <para>When the server recovers this leaves the client in a difficult situation. It knows the - target server failed, but it does not know if the last message reached its destination ok. - If it decides to resend the last message, then that could result in a duplicate message - being sent to the address. If each message was an order or a trade then this could result in - the order being fulfilled twice or the trade being double booked. This is clearly not a - desirable situation.</para> - <para>Sending the message(s) in a transaction does not help out either. If the server or - connection fails while the transaction commit is being processed it is also indeterminate - whether the transaction was successfully committed or not!</para> - <para>To solve these issues ActiveMQ provides automatic duplicate messages detection for - messages sent to addresses.</para> - <section> - <title>Using Duplicate Detection for Message Sending</title> - <para>Enabling duplicate message detection for sent messages is simple: you just need to set - a special property on the message to a unique value. You can create the value however - you like, as long as it is unique. When the target server receives the message it will - check if that property is set, if it is, then it will check in its in memory cache if it - has already received a message with that value of the header. If it has received a - message with the same value before then it will ignore the message.</para> - <note> - <para>Using duplicate detection to move messages between nodes can give you the same - <emphasis>once and only once</emphasis> delivery guarantees as if you were using - an XA transaction to consume messages from source and send them to the target, but - with less overhead and much easier configuration than using XA.</para> - </note> - <para>If you're sending messages in a transaction then you don't have to set the property - for <emphasis>every</emphasis> message you send in that transaction, you only need to - set it once in the transaction. If the server detects a duplicate message for any - message in the transaction, then it will ignore the entire transaction.</para> - <para>The name of the property that you set is given by the value of <literal - >org.apache.activemq.api.core.Message.HDR_DUPLICATE_DETECTION_ID</literal>, which - is <literal>_HQ_DUPL_ID</literal></para> - <para>The value of the property can be of type <literal>byte[]</literal> or <literal - >SimpleString</literal> if you're using the core API. If you're using JMS it must be - a <literal>String</literal>, and its value should be unique. An easy way of generating - a unique id is by generating a UUID.</para> - <para>Here's an example of setting the property using the core API:</para> - <programlisting> -... - -ClientMessage message = session.createMessage(true); - -SimpleString myUniqueID = "This is my unique id"; // Could use a UUID for this - -message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, myUniqueID); - -...</programlisting> - <para>And here's an example using the JMS API:</para> - <programlisting> -... - -Message jmsMessage = session.createMessage(); - -String myUniqueID = "This is my unique id"; // Could use a UUID for this - -message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID); - -...</programlisting> - </section> - <section id="duplicate.id.cache"> - <title>Configuring the Duplicate ID Cache</title> - <para>The server maintains caches of received values of the <literal - >org.apache.activemq.core.message.impl.HDR_DUPLICATE_DETECTION_ID</literal> property - sent to each address. Each address has its own distinct cache.</para> - <para>The cache is a circular fixed size cache. If the cache has a maximum size of <literal - >n</literal> elements, then the <literal>n + 1</literal>th id stored will overwrite - the <literal>0</literal>th element in the cache.</para> - <para>The maximum size of the cache is configured by the parameter <literal - >id-cache-size</literal> in <literal>activemq-configuration.xml</literal>, the default - value is <literal>2000</literal> elements.</para> - <para>The caches can also be configured to persist to disk or not. This is configured by the - parameter <literal>persist-id-cache</literal>, also in <literal - >activemq-configuration.xml</literal>. If this is set to <literal>true</literal> then - each id will be persisted to permanent storage as they are received. The default value - for this parameter is <literal>true</literal>.</para> - <note> - <para>When choosing a size of the duplicate id cache be sure to set it to a larger - enough size so if you resend messages all the previously sent ones are in the cache - not having been overwritten.</para> - </note> - </section> - <section> - <title>Duplicate Detection and Bridges</title> - <para>Core bridges can be configured to automatically add a unique duplicate id value (if there - isn't already one in the message) before forwarding the message to it's target. This - ensures that if the target server crashes or the connection is interrupted and the - bridge resends the message, then if it has already been received by the target server, - it will be ignored.</para> - <para>To configure a core bridge to add the duplicate id header, simply set the <parameter - >use-duplicate-detection</parameter> to <literal>true</literal> when configuring a - bridge in <literal>activemq-configuration.xml</literal>.</para> - <para>The default value for this parameter is <literal>true</literal>.</para> - <para>For more information on core bridges and how to configure them, please see - <xref linkend="core-bridges" />.</para> - </section> - <section> - <title>Duplicate Detection and Cluster Connections</title> - <para>Cluster connections internally use core bridges to move messages reliable between - nodes of the cluster. Consequently they can also be configured to insert the duplicate - id header for each message they move using their internal bridges.</para> - <para>To configure a cluster connection to add the duplicate id header, simply set the - <parameter>use-duplicate-detection</parameter> to <literal>true</literal> when - configuring a cluster connection in <literal>activemq-configuration.xml</literal>.</para> - <para>The default value for this parameter is <literal>true</literal>.</para> - <para>For more information on cluster connections and how to configure them, please see <xref - linkend="clusters"/>.</para> - </section> -</chapter> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/4245a6b4/docs/user-manual/en/embedding-activemq.md ---------------------------------------------------------------------- diff --git a/docs/user-manual/en/embedding-activemq.md b/docs/user-manual/en/embedding-activemq.md new file mode 100644 index 0000000..0c29d59 --- /dev/null +++ b/docs/user-manual/en/embedding-activemq.md @@ -0,0 +1,225 @@ +Embedding ActiveMQ +================== + +ActiveMQ is designed as set of simple Plain Old Java Objects (POJOs). +This means ActiveMQ can be instantiated and run in any dependency +injection framework such as JBoss Microcontainer, Spring or Google +Guice. It also means that if you have an application that could use +messaging functionality internally, then it can *directly instantiate* +ActiveMQ clients and servers in its own application code to perform that +functionality. We call this *embedding* ActiveMQ. + +Examples of applications that might want to do this include any +application that needs very high performance, transactional, persistent +messaging but doesn't want the hassle of writing it all from scratch. + +Embedding ActiveMQ can be done in very few easy steps. Instantiate the +configuration object, instantiate the server, start it, and you have a +ActiveMQ running in your virtual machine. It's as simple and easy as +that. + +Simple Config File Embedding +============================ + +The simplest way to embed ActiveMQ is to use the embedded wrapper +classes and configure ActiveMQ through its configuration files. There +are two different helper classes for this depending on whether your +using the ActiveMQ Core API or JMS. + +Core API Only +------------- + +For instantiating a core ActiveMQ Server only, the steps are pretty +simple. The example requires that you have defined a configuration file +`activemq-configuration.xml` in your classpath: + + import org.apache.activemq.core.server.embedded.EmbeddedActiveMQ; + + ... + + EmbeddedActiveMQ embedded = new EmbeddedActiveMQ(); + embedded.start(); + + ClientSessionFactory nettyFactory = ActiveMQClient.createClientSessionFactory( + new TransportConfiguration( + InVMConnectorFactory.class.getName())); + + ClientSession session = factory.createSession(); + + session.createQueue("example", "example", true); + + ClientProducer producer = session.createProducer("example"); + + ClientMessage message = session.createMessage(true); + + message.getBody().writeString("Hello"); + + producer.send(message); + + session.start(); + + ClientConsumer consumer = session.createConsumer("example"); + + ClientMessage msgReceived = consumer.receive(); + + System.out.println("message = " + msgReceived.getBody().readString()); + + session.close(); + +The `EmbeddedActiveMQ` class has a few additional setter methods that +allow you to specify a different config file name as well as other +properties. See the javadocs for this class for more details. + +JMS API +------- + +JMS embedding is simple as well. This example requires that you have +defined the config files `activemq-configuration.xml`, +`activemq-jms.xml`, and a `activemq-users.xml` if you have security +enabled. Let's also assume that a queue and connection factory has been +defined in the `activemq-jms.xml` config file. + + import org.apache.activemq.jms.server.embedded.EmbeddedJMS; + + ... + + EmbeddedJMS jms = new EmbeddedJMS(); + jms.start(); + + // This assumes we have configured activemq-jms.xml with the appropriate config information + ConnectionFactory connectionFactory = jms.lookup("ConnectionFactory"); + Destination destination = jms.lookup("/example/queue"); + + ... regular JMS code ... + +By default, the `EmbeddedJMS` class will store component entries defined +within your `activemq-jms.xml` file in an internal concurrent hash map. +The `EmbeddedJMS.lookup()` method returns components stored in this map. +If you want to use JNDI, call the `EmbeddedJMS.setContext()` method with +the root JNDI context you want your components bound into. See the +javadocs for this class for more details on other config options. + +POJO instantiation - Embedding Programmatically +=============================================== + +You can follow this step-by-step guide to programmatically embed the +core, non-JMS ActiveMQ Server instance: + +Create the configuration object - this contains configuration +information for a ActiveMQ instance. The setter methods of this class +allow you to programmatically set configuration options as describe in +the ? section. + +The acceptors are configured through `ConfigurationImpl`. Just add the +`NettyAcceptorFactory` on the transports the same way you would through +the main configuration file. + + import org.apache.activemq.core.config.Configuration; + import org.apache.activemq.core.config.impl.ConfigurationImpl; + + ... + + Configuration config = new ConfigurationImpl(); + HashSet<TransportConfiguration> transports = new HashSet<TransportConfiguration>(); + + transports.add(new TransportConfiguration(NettyAcceptorFactory.class.getName())); + transports.add(new TransportConfiguration(InVMAcceptorFactory.class.getName())); + + config.setAcceptorConfigurations(transports); + +You need to instantiate an instance of +`org.apache.activemq.api.core.server.embedded.EmbeddedActiveMQ` and add +the configuration object to it. + + import org.apache.activemq.api.core.server.ActiveMQ; + import org.apache.activemq.core.server.embedded.EmbeddedActiveMQ; + + ... + + EmbeddedActiveMQ server = new EmbeddedActiveMQ(); + server.setConfiguration(config); + + server.start(); + +You also have the option of instantiating `ActiveMQServerImpl` directly: + + ActiveMQServer server = new ActiveMQServerImpl(config); + server.start(); + +For JMS POJO instantiation, you work with the EmbeddedJMS class instead +as described earlier. First you define the configuration +programmatically for your ConnectionFactory and Destination objects, +then set the JmsConfiguration property of the EmbeddedJMS class. Here is +an example of this: + + // Step 1. Create ActiveMQ core configuration, and set the properties accordingly + Configuration configuration = new ConfigurationImpl(); + configuration.setPersistenceEnabled(false); + configuration.setSecurityEnabled(false); + configuration.getAcceptorConfigurations().add(new TransportConfiguration(NettyAcceptorFactory.class.getName())); + + // Step 2. Create the JMS configuration + JMSConfiguration jmsConfig = new JMSConfigurationImpl(); + + // Step 3. Configure the JMS ConnectionFactory + TransportConfiguration connectorConfig = new TransportConfiguration(NettyConnectorFactory.class.getName()); + ConnectionFactoryConfiguration cfConfig = new ConnectionFactoryConfigurationImpl("cf", connectorConfig, "/cf"); + jmsConfig.getConnectionFactoryConfigurations().add(cfConfig); + + // Step 4. Configure the JMS Queue + JMSQueueConfiguration queueConfig = new JMSQueueConfigurationImpl("queue1", null, false, "/queue/queue1"); + jmsConfig.getQueueConfigurations().add(queueConfig); + + // Step 5. Start the JMS Server using the ActiveMQ core server and the JMS configuration + EmbeddedJMS jmsServer = new EmbeddedJMS(); + jmsServer.setConfiguration(configuration); + jmsServer.setJmsConfiguration(jmsConfig); + jmsServer.start(); + +Please see ? for an example which shows how to setup and run ActiveMQ +embedded with JMS. + +Dependency Frameworks +===================== + +You may also choose to use a dependency injection framework such as +JBoss Micro Container or Spring Framework. See ? for more details on +Spring and ActiveMQ, but here's how you would do things with the JBoss +Micro Container. + +ActiveMQ standalone uses JBoss Micro Container as the injection +framework. `ActiveMQBootstrapServer` and `activemq-beans.xml` which are +part of the ActiveMQ distribution provide a very complete implementation +of what's needed to bootstrap the server using JBoss Micro Container. + +When using JBoss Micro Container, you need to provide an XML file +declaring the `ActiveMQServer` and `Configuration` object, you can also +inject a security manager and a MBean server if you want, but those are +optional. + +A very basic XML Bean declaration for the JBoss Micro Container would +be: + + <?xml version="1.0" encoding="UTF-8"?> + <deployment xmlns="urn:jboss:bean-deployer:2.0"> + <!-- The core configuration --> + <bean name="Configuration" + class="org.apache.activemq.core.config.impl.FileConfiguration"> + </bean> + + <!-- The core server --> + <bean name="ActiveMQServer" + class="org.apache.activemq.core.server.impl.ActiveMQServerImpl"> + <constructor> + <parameter> + <inject bean="Configuration"/> + </parameter> + </constructor> + </bean> + </deployment> + +`ActiveMQBootstrapServer` provides an easy encapsulation of JBoss Micro +Container. + + ActiveMQBootstrapServer bootStrap = new ActiveMQBootstrapServer(new String[] {"activemq-beans.xml"}); + bootStrap.run();
