You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by bu...@apache.org on 2016/09/16 23:22:09 UTC

svn commit: r997547 - in /websites/production/activemq/content: cache/main.pageCache message-groups.html slow-consumer-handling.html

Author: buildbot
Date: Fri Sep 16 23:22:09 2016
New Revision: 997547

Log:
Production update by buildbot for activemq

Modified:
    websites/production/activemq/content/cache/main.pageCache
    websites/production/activemq/content/message-groups.html
    websites/production/activemq/content/slow-consumer-handling.html

Modified: websites/production/activemq/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.

Modified: websites/production/activemq/content/message-groups.html
==============================================================================
--- websites/production/activemq/content/message-groups.html (original)
+++ websites/production/activemq/content/message-groups.html Fri Sep 16 23:22:09 2016
@@ -36,6 +36,7 @@
       <link href='http://activemq.apache.org/styles/highlighter/styles/shThemeEclipse.css' rel='stylesheet' type='text/css' /> 
       <script src='http://activemq.apache.org/styles/highlighter/scripts/shCore.js' type='text/javascript'></script> 
               <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushJava.js' type='text/javascript'></script> 
+              <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushXml.js' type='text/javascript'></script> 
          
       <script type="text/javascript"> 
         SyntaxHighlighter.defaults['toolbar'] = false; 
@@ -81,120 +82,36 @@
   <tbody>
         <tr>
         <td valign="top" width="100%">
-<div class="wiki-content maincontent"><h2 id="MessageGroups-MessageGroups">Message Groups</h2>
-
-<p>Message Groups rock! <img class="emoticon emoticon-smile" src="https://cwiki.apache.org/confluence/s/en_GB/5982/f2b47fb3d636c8bc9fd0b11c0ec6d0ae18646be7.1/_/images/icons/emoticons/smile.png" data-emoticon-name="smile" alt="(smile)"> They are an enhancement to the <a shape="rect" href="exclusive-consumer.html">Exclusive Consumer</a> feature to provide</p>
-
-<ul><li>guarranteed ordering of the processing of related messages across a single queue</li><li>load balancing of the processing of messages across multiple consumers</li><li>high availability / auto-failover to other consumers if a JVM goes down</li></ul>
-
-
-<p>So logically Message Groups are kinda like a parallel <a shape="rect" href="exclusive-consumer.html">Exclusive Consumer</a>. Rather than all messages going to a single consumer, the standard JMS header <strong>JMSXGroupID</strong> is used to define which <em>message group</em> the message belongs to. The Message Group feature then ensures that all messages for the same message group will be sent to the same JMS consumer - while that consumer stays alive. As soon as the consumer dies another will be chosen.</p>
-
-<p>Another way of explaining Message Groups is that it provides sticky load balancing of messages across consumers; where the JMSXGroupID is kinda like a HTTP session ID or cookie value and the message broker is acting like a HTTP load balancer.</p>
-
-<h3 id="MessageGroups-ExampleUseCase">Example Use Case</h3>
-
-<p>Lets say we are doing some kind of order matching system where people are buying and selling things (stocks, shares, placing online bets, whatever).</p>
-
-<p>You want to have consumers who match bids and offers for different items (stocks / bets) so they want to keep in RAM for performance a sub-set of the data set.</p>
-
-<p>So set the JMSXGroupID to be MSFT, IBM, SUNW and so forth to use the stock symbol to define the message group. (It can be any string whatsoever; maybe combining trading book, trading exchange, date and so forth - the more specific the group ID, the more concurrent you can run).</p>
-
-<p>So assuming we are buying and selling MSFT, IBM, SUNW shares; the Message Groups feature guarrentees that all the MSFT messages will be processed in order by the same consumer; ditto for IBM and SUNW.</p>
-
-<h3 id="MessageGroups-HowMessageGroupswork">How Message Groups work</h3>
-
-<p>When a message is being dispatched to a consumer, the JMSXGroupID is checked. If one is present then the broker checks to see if a consumer owns that message group. (Since there could be a massive number of individual message groups we use hash buckets rather than the actual JMSXGroupID string).</p>
-
-<p>If no consumer is associated with a message group a consumer is chosen. That JMS MessageConsumer will receive all further messages with the same JMSXGroupID value until</p>
-
-<ul><li>the consumer closes (or the client which created the consumer dies etc)</li><li>someone closes the message group by sending a message with a negative value for JMSXGroupSeq (see below for more details)</li></ul>
-
-
-<p>Note: like message selector matching, grouping based on JMSXGroupID occurs before dispatch on messages in memory. With the default maxPageSize setting, large backlogs of messages destined for one group they can block receipt of messages to other groups if they don't all fit in memory. You can change the default maxPageSize setting for destinations as follows:</p>
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-  &lt;destinationPolicy&gt;
-      &lt;policyMap&gt;
-         &lt;policyEntries&gt;
-             &lt;policyEntry queue="&gt;" maxPageSize="1000"/&gt;
-         &lt;/policyEntries&gt;
-      &lt;/policyMap&gt;
-  &lt;/destinationPolicy&gt;</pre>
-</div></div>
-
-<h3 id="MessageGroups-UsingMessageGroups">Using Message Groups</h3>
-
-<p>You just need to change your JMS producers to fill in the <strong>JMSXGroupID</strong> message header with some String value of your choice. e.g.</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-Mesasge message = session.createTextMessage("&lt;foo&gt;hey&lt;/foo&gt;");
+<div class="wiki-content maincontent"><h2 id="MessageGroups-MessageGroups">Message Groups</h2><p>Message Groups are an enhancement to the <a shape="rect" href="exclusive-consumer.html">Exclusive Consumer</a> feature. They provide:</p><ul><li>Guaranteed ordering of the processing of related messages across a single queue.</li><li>Load balancing of the processing of messages across multiple consumers.</li><li>High availability / auto-failover to other consumers if a JVM goes down.</li></ul><p>So logically Message Groups are like a parallel <a shape="rect" href="exclusive-consumer.html">Exclusive Consumer</a>. Rather than all messages going to a single consumer, the standard JMS header&#160;<strong><code>JMSXGroupID</code></strong> is used to define which <em>message group</em> the message belongs to. The Message Group feature then ensures that all messages for the <em>same</em> message group will be sent to the <em>same</em> JMS consumer - whilst that consumer stays alive. As soon as 
 the consumer dies another will be chosen.</p><p>Another way of explaining Message Groups is that it provides sticky load balancing of messages across consumers; where the&#160;<strong><code>JMSXGroupID</code></strong> is kinda like a HTTP session ID or cookie value and the message broker is acting like a HTTP load balancer.</p><h3 id="MessageGroups-ExampleUseCase">Example Use Case</h3><p>Lets say we are doing some kind of order matching system where people are buying and selling things (stocks, shares, placing online bets, whatever). You want to have consumers who match bids and offers for different items (stocks / bets) so they want to keep in RAM for performance a sub-set of the data set. Therefore set the&#160;<strong><code>JMSXGroupID</code></strong> to be <strong><code>MSFT</code></strong>, <strong><code>IBM</code></strong>,&#160;<strong><code>SUNW</code></strong> and so forth to use the stock symbol to define the message group. (It can be any string whatsoever; maybe combining
  trading book, trading exchange, date and so forth - the more specific the group ID, the more concurrent you can run). Assume we are buying and selling <strong><code>MSFT</code>, <code>IBM</code>,&#160;<code>SUNW</code></strong> shares; the Message Groups feature guarantees that all the&#160;<strong><code>MSFT</code></strong> messages will be processed in order by the same consumer; ditto for&#160;<strong><code>IBM</code></strong> and <strong><code>SUNW</code></strong>.</p><h3 id="MessageGroups-HowMessageGroupsWork">How Message Groups Work</h3><p>When a message is being dispatched to a consumer, the&#160;<strong><code>JMSXGroupID</code></strong> is checked. If one is present then the broker checks to see if a consumer owns that message group. Since there could be a large number of message groups hash buckets are used rather than the actual&#160;<strong><code>JMSXGroupID</code></strong> string.</p><p>If no consumer is associated with a message group a consumer is chosen. Said JMS&#16
 0;<strong><code>MessageConsumer</code></strong> will receive all further messages with the same&#160;<strong><code>JMSXGroupID</code></strong> value until:</p><ul><li>the consumer closes (or the client which created the consumer dies etc).</li><li>someone closes the message group by sending a message with a negative value for&#160;<strong><code>JMSXGroupSeq</code></strong> (see below for more details).</li></ul><p><strong>Note</strong>: as with message selector matching, grouping based on&#160;<strong><code>JMSXGroupID</code></strong> occurs before dispatch on messages in memory. With the default&#160;<strong><code>maxPageSize</code></strong> option, large backlogs of messages destined for one group can block receipt of messages to other groups if they don't all fit in memory. You can change the default&#160;<strong><code>maxPageSize</code></strong> setting for destinations as follows:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl
 ">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;destinationPolicy&gt;
+    &lt;policyMap&gt;
+       &lt;policyEntries&gt;
+           &lt;policyEntry queue="&gt;" maxPageSize="1000"/&gt;
+       &lt;/policyEntries&gt;
+    &lt;/policyMap&gt;
+&lt;/destinationPolicy&gt;</pre>
+</div></div><h3 id="MessageGroups-UsingMessageGroups">Using Message Groups</h3><p>You just need to change your JMS producers to fill in the&#160;<strong><code>JMSXGroupID</code></strong> message header with some&#160;<strong><code>String</code></strong> value of your choice.</p><p>Example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">Mesasge message = session.createTextMessage("&lt;foo&gt;hey&lt;/foo&gt;");
 message.setStringProperty("JMSXGroupID", "IBM_NASDAQ_20/4/05");
 ...
 producer.send(message);
 </pre>
-</div></div>
-
-
-<h3 id="MessageGroups-ClosingaMessageGroup">Closing a Message Group</h3>
-
-<p>You generally don't need to close a message group; just keep using it. However if you really do want to close a group you can add a negative sequence number.</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-Mesasge message = session.createTextMessage("&lt;foo&gt;hey&lt;/foo&gt;");
+</div></div><h3 id="MessageGroups-ClosingaMessageGroup">Closing a Message Group</h3><p>You generally don't need to close a message group; just keep using it. However if you really do want to close a group you can add a negative sequence number.</p><p>Example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">Mesasge message = session.createTextMessage("&lt;foo&gt;hey&lt;/foo&gt;");
 message.setStringProperty("JMSXGroupID", "IBM_NASDAQ_20/4/05");
 message.setIntProperty("JMSXGroupSeq", -1);
 ...
 producer.send(message);
 </pre>
-</div></div>
-
-<p>This then <em>closes</em> the message group so if another message is sent in the future with the same message group ID it will be reassigned to a new consumer.</p>
-
-<h3 id="MessageGroups-Impliciations">Impliciations</h3>
-
-<p>Message Groups mean you get the power of <strong>grid</strong> processing of messages across a cluster of consumers with reliability, auto-failover, load balancing but you can also order the processing of messages too. So its the best of both worlds.</p>
-
-<p>However using the above example, what Message Groups actually do is to partition your work load across consumers using a user defineable partition strategy - the JMSXGroupID value.</p>
-
-<p>The neat thing about this is that you can do neat things like use lots of RAM caching; keep the order for MSFT in RAM in the MSFT consumer; keep the IBM orders in RAM in the IBM consumer - since the message broker is partitioning for you, you do not have to rely on a distributed cache with inter-cache synchronisation and locking to take advantage of caching.</p>
-
-<p>The great thing is - to the application developer, it looks like a simple 1 consumer world where you process messages and do your job; leaving the broker to do all the hard stuff for you</p>
-
-<ul><li>partioning the traffic</li><li>load balancing of message groups across consumers</li><li>auto-failover of groups to different consumers as consumers come and go</li></ul>
-
-
-<p>In summary; if ordering or per-message caching and synchronization are in any way important to you then we highly recommend you use message groups to partition your traffic.</p>
-
-<h3 id="MessageGroups-Gettingnotifiedofownershipchangesofmessagegroups">Getting notified of ownership changes of message groups</h3>
+</div></div><p>This then <em>closes</em> the message group so if another message is sent in the future with the same message group ID it will be reassigned to a new consumer.</p><h3 id="MessageGroups-Implications">Implications</h3><p>Message Groups mean you get the power of <strong>grid</strong> processing of messages across a cluster of consumers with reliability, auto-failover, load balancing but you can also order the processing of messages too. So its the best of both worlds. However using the above example, what Message Groups actually do is to partition your work load across consumers using a user definable partition strategy - the&#160;<strong><code>JMSXGroupID</code></strong> value.</p><p>The neat thing about this is that you can do neat things like use lots of RAM caching; keep the order for&#160;<strong><code>MSFT</code></strong> in RAM in the&#160;<strong><code>MSFT</code></strong> consumer; keep the&#160;<strong><code>IBM</code></strong> orders in RAM in the&#160;<strong
 ><code>IBM</code></strong> consumer - since the message broker is partitioning for you, you do not have to rely on a distributed cache with inter-cache synchronization and locking to take advantage of caching.</p><p>The great thing is - to the application developer, it looks like a simple 1 consumer world where you process messages and do your job; leaving the broker to do all the hard stuff for you</p><ul><li>partitioning the traffic</li><li>load balancing of message groups across consumers</li><li>auto-failover of groups to different consumers as consumers come and go</li></ul><p>In summary; if ordering or per-message caching and synchronization are in any way important to you then we highly recommend you use message groups to partition your traffic.</p><h3 id="MessageGroups-GettingNotifiedofOwnershipChangesofMessageGroups">Getting Notified of Ownership Changes of Message Groups</h3><p>ActiveMQ support a boolean header called&#160;<strong><code>JMSXGroupFirstForConsumer</code></st
 rong>. This header is set on the first message sent to a consumer for a particular message group.</p><p>If the JMS connection is using&#160;<strong><code>failover:</code></strong> and a temporary network error occurs so that the connection disconnects from the broker and reconnects some time later, a new consumer instance will be created under the covers of the JMS client leading to the possibility of another message with this header being set for the same message group.</p><p>Example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">String groupId = message.getStringProperty("JMSXGroupId");
 
-<p>In 4.1 onwards of ActiveMQ there is support for a new boolean header called <strong>JMSXGroupFirstForConsumer</strong> which will be set on the first message which is sent to a consumer for a particular message group.</p>
-
-<p>If the JMS connection is using <strong>failover:</strong> and a temporary network error occurs so that the connection disconnects from the broker and reconnects some time later, a new consumer instance will be created under the covers of the JMS client leading to the possibility of another message with this header being set for the same message group.</p>
-
-<p>So you can do code like...</p>
-
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
-String groupId = message.getStringProperty("JMSXGroupId");
 if (message.getBooleanProperty("JMSXGroupFirstForConsumer")) {
    // flush cache for groupId
 }
 </pre>
-</div></div>
-
-<p>To flush caches to ensure consistent state when faced with network errors.</p>
-
-<h3 id="MessageGroups-Addingnewconsumers">Adding new consumers</h3>
-
-<p>If you have existing messages in the broker and add consumers at a later stage, it is a good idea to delay message dispatch start until all consumers are present (or at least to give enough time for them to subscribe). If you don't do that the first consumer will probably acquire all message groups and all messages will be dispatched to it. You can achieve this by using <code>consumersBeforeDispatchStarts</code> and <code>timeBeforeDispatchStarts</code> <a shape="rect" href="per-destination-policies.html">destination policies</a>. </p>
-
-<p>Here's the example of the destination policy that delays dispatch for 200ms</p>
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">                
-&lt;destinationPolicy&gt;
+</div></div><p>To flush caches to ensure consistent state when faced with network errors.</p><h3 id="MessageGroups-AddingNewConsumers">Adding New Consumers</h3><p>If you have existing messages in the broker and add consumers at a later stage, it is a good idea to delay message dispatch start until all consumers are present (or at least to give enough time for them to subscribe). If you don't do that the first consumer will probably acquire all message groups and all messages will be dispatched to it. You can achieve this by using <strong><code>consumersBeforeDispatchStarts</code></strong> and <strong><code>timeBeforeDispatchStarts</code></strong> <a shape="rect" href="per-destination-policies.html">destination policies</a>.</p><p>Here's the example of the destination policy that delays dispatch for&#160;<strong><code>200ms</code></strong>:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;destinationPolicy&gt;
   &lt;policyMap&gt;
     &lt;policyEntries&gt;
       &lt;policyEntry queue="&gt;" timeBeforeDispatchStarts="200"/&gt;
@@ -202,11 +119,8 @@ if (message.getBooleanProperty("JMSXGrou
   &lt;/policyMap&gt;
 &lt;/destinationPolicy&gt;
 </pre>
-</div></div>
-<p>The following code snippet shows how to wait for two consumers (or two seconds) before dispatch starts</p>
-<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">                
-&lt;destinationPolicy&gt;
+</div></div><p>The following code snippet shows how to wait for two consumers (or two seconds) before dispatch starts:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;destinationPolicy&gt;
   &lt;policyMap&gt;
     &lt;policyEntries&gt;
       &lt;policyEntry queue="&gt;" consumersBeforeDispatchStarts="2" timeBeforeDispatchStarts="2000"/&gt;
@@ -214,16 +128,7 @@ if (message.getBooleanProperty("JMSXGrou
   &lt;/policyMap&gt;
 &lt;/destinationPolicy&gt;
 </pre>
-</div></div>
-
-<p>As <a shape="rect" class="external-link" href="http://svn.apache.org/viewvc/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/usecases/MessageGroupDelayedTest.java?view=markup">the appropriate test case</a> shows, adding a small time pause before dispatching or setting a minimum consumer number, ensures equal message group distribution.</p>
-
-<div class="confluence-information-macro confluence-information-macro-note"><p class="title">Availability</p><span class="aui-icon aui-icon-small aui-iconfont-warning confluence-information-macro-icon"></span><div class="confluence-information-macro-body">
-<p>Available since version 5.3</p></div></div>
-
-<h3 id="MessageGroups-See">See</h3>
-
-<ul><li><a shape="rect" href="how-do-message-groups-compare-to-selectors.html">How do Message Groups compare to Selectors</a></li></ul></div>
+</div></div><p>As <a shape="rect" class="external-link" href="http://svn.apache.org/viewvc/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/usecases/MessageGroupDelayedTest.java?view=markup">the appropriate test case</a> shows, adding a small time pause before dispatching or setting a minimum consumer number, ensures equal message group distribution.</p><div class="confluence-information-macro confluence-information-macro-note"><p class="title">Availability</p><span class="aui-icon aui-icon-small aui-iconfont-warning confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>Available since version 5.3</p></div></div><h3 id="MessageGroups-See">See</h3><ul><li><a shape="rect" href="how-do-message-groups-compare-to-selectors.html">How do Message Groups compare to Selectors</a></li></ul></div>
         </td>
         <td valign="top">
           <div class="navigation">

Modified: websites/production/activemq/content/slow-consumer-handling.html
==============================================================================
--- websites/production/activemq/content/slow-consumer-handling.html (original)
+++ websites/production/activemq/content/slow-consumer-handling.html Fri Sep 16 23:22:09 2016
@@ -35,7 +35,6 @@
           <link href='http://activemq.apache.org/styles/highlighter/styles/shCore.css' rel='stylesheet' type='text/css' /> 
       <link href='http://activemq.apache.org/styles/highlighter/styles/shThemeEclipse.css' rel='stylesheet' type='text/css' /> 
       <script src='http://activemq.apache.org/styles/highlighter/scripts/shCore.js' type='text/javascript'></script> 
-              <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushJava.js' type='text/javascript'></script> 
               <script src='http://activemq.apache.org/styles/highlighter/scripts/shBrushXml.js' type='text/javascript'></script> 
          
       <script type="text/javascript"> 
@@ -82,70 +81,82 @@
   <tbody>
         <tr>
         <td valign="top" width="100%">
-<div class="wiki-content maincontent"><p><a shape="rect" href="slow-consumers.html">Slow Consumers</a> can cause problems on non-durable topics since they can force the broker to keep old messages in RAM which once it fills up, forces the broker to slow down producers, causing the fast consumers to be slowed down. One option we could implement in the future is spooling to disk - but then spooling to disk could slow down the fast consumers too.</p><p>Currently we have a strategy that lets you configure the maximum number of matched messages the broker will keep around for a consumer in addition to its prefetch buffer. Once this maximum is reached, as new messages come in, older messages are discarded. This allows you to keep the RAM for current messages and keep sending messages to a slow consumer but to discard old messages.</p><h2 id="SlowConsumerHandling-PendingMessageLimitStrategy">Pending Message Limit Strategy</h2><p>You can configure the PendingMessageLimitStrategy implementat
 ion class on the destination map so that different regions of your topic namespace can have different strategies for dealing with slow consumers. For example you may want to use this strategy for prices which are very high volume but for orders and trades which are lower volume you might not wish to discard old messages.</p><p>The strategy calculates the maximum number of pending messages to be kept in RAM for a consumer (above its prefetch size). A value of zero means keep no messages around other than the prefetch amount. A value greater than zero will keep up to that amount of messages around, discarding the older messages as new messages come in. A value of -1 disables the discarding of messages.</p><p>We currently have 2 different implementations of the strategy.</p><h3 id="SlowConsumerHandling-ConstantPendingMessageLimitStrategy">ConstantPendingMessageLimitStrategy</h3><p>This strategy uses a constant limit for all consumers (above their prefetch size). e.g.</p><div class="cod
 e panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;constantPendingMessageLimitStrategy limit="50"/&gt;
+<div class="wiki-content maincontent"><p><a shape="rect" href="slow-consumers.html">Slow Consumers</a> can cause problems on non-durable topics since they can force the broker to keep old messages in RAM which once it fills up, forces the broker to slow down producers, causing the fast consumers to be slowed down. One option we could implement in the future is spooling to disk - but then spooling to disk could slow down the fast consumers too.</p><p>Currently we have a strategy that lets you configure the maximum number of matched messages the broker will keep around for a consumer in addition to its prefetch buffer. Once this maximum is reached, as new messages come in, older messages are discarded. This allows you to keep the RAM for current messages and keep sending messages to a slow consumer but to discard old messages.</p><h2 id="SlowConsumerHandling-PendingMessageLimitStrategy">Pending Message Limit Strategy</h2><p>You can configure the&#160;<strong><code>PendingMessageLimitS
 trategy</code></strong> implementation class on the destination map so that different regions of your topic namespace can have different strategies for dealing with slow consumers. For example you may want to use this strategy for prices which are very high volume but for orders and trades which are lower volume you might not wish to discard old messages.</p><p>The strategy calculates the maximum number of pending messages to be kept in RAM for a consumer (above its prefetch size). A value of zero means keep no messages around other than the prefetch amount. A value greater than zero will keep up to that amount of messages around, discarding the older messages as new messages come in. A value of&#160;<strong><code>-1</code></strong> disables the discarding of messages.</p><p>There are currently two different implementations of the strategy:</p><ul><li><strong><code>ConstantPendingMessageLimitStrategy</code></strong></li><li><strong><code>PrefetchRatePendingMessageLimitStrategy</code
 ></strong></li></ul><h3 id="SlowConsumerHandling-ConstantPendingMessageLimitStrategy">ConstantPendingMessageLimitStrategy</h3><p>This strategy uses a constant limit for all consumers (above their prefetch size).</p><p>Example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;constantPendingMessageLimitStrategy limit="50"/&gt;
 </pre>
 </div></div><h3 id="SlowConsumerHandling-PrefetchRatePendingMessageLimitStrategy">PrefetchRatePendingMessageLimitStrategy</h3><p>This strategy calculates the maximum number of pending messages using a multiplier of the consumers prefetch size. So you could for example keep around 2.5 times the prefetch count for each consumer.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;prefetchRatePendingMessageLimitStrategy multiplier="2.5"/&gt;
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;prefetchRatePendingMessageLimitStrategy multiplier="2.5"/&gt;
 </pre>
-</div></div><h3 id="SlowConsumerHandling-UsingthePrefetchPolicytoconfigurethelimit">Using the Prefetch Policy to configure the limit</h3><p>The JMS Client has a <a shape="rect" href="what-is-the-prefetch-limit-for.html">prefetch policy</a> you can use to configure the various prefetch limits for persistent &amp; non persistent queues &amp; topics. The prefetch policy also allows you to specify the maximumPendingMessageLimit on a per connection/consumer basis.</p><p>One minor difference with configuring this value; to simplify operation with non-JMS clients such as with <a shape="rect" href="openwire.html">OpenWire</a> the value of zero is ignored; so the lowest value you can configure is 1.</p><h3 id="SlowConsumerHandling-ConfiguringtheEvictionPolicy">Configuring the Eviction Policy</h3><p>We have a MessageEvictionStrategy which is used to decide which message should be evicted on a slow consumer. The default implementation is</p><div class="code panel pdl" style="border-width: 1px;
 "><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;oldestMessageEvictionStrategy/&gt;
+</div></div><h3 id="SlowConsumerHandling-UsingthePrefetchPolicytoConfiguretheLimit">Using the Prefetch Policy to Configure the Limit</h3><p>The JMS Client has a <a shape="rect" href="what-is-the-prefetch-limit-for.html">prefetch policy</a> you can use to configure the various prefetch limits for persistent and non persistent queues and topics. The prefetch policy also allows you to specify the&#160;<strong><code>maximumPendingMessageLimit</code></strong> on a per connection/consumer basis. One minor difference with configuring this value; to simplify operation with non-JMS clients such as with <a shape="rect" href="openwire.html">OpenWire</a> the value of zero is ignored; so the lowest value you can configure is <strong><code>1</code></strong>.</p><h3 id="SlowConsumerHandling-ConfiguringtheEvictionPolicy">Configuring the Eviction Policy</h3><p>We have a&#160;<strong><code>MessageEvictionStrategy</code></strong> which is used to decide which message should be evicted on a slow consum
 er. The default implementation is:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;oldestMessageEvictionStrategy/&gt;
 </pre>
-</div></div><p>But you can write your own to use some application specific way of choosing. e.g. if you are sending market data price updates, you may wish to find an older price value, which might not be the oldest message. The implementation of this eviction strategy could be set (since version 5.6) using</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;uniquePropertyMessageEvictionStrategy propertyName="STOCK" /&gt;
+</div></div><p>However, you can write your own to use some application specific way of choosing messages for eviction. For example, if you are sending market data price updates you may wish to find an older price value, which might not be the oldest message.</p><p>Example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;uniquePropertyMessageEvictionStrategy propertyName="STOCK"/&gt;
 </pre>
-</div></div><p>where <code>propertyName</code> is the JMS message property that specifies the price.</p><p>Another option could be to use the oldest message with the lowest priority message - so if you have some high priority messages, evict the lower priority messages first even if they are newer.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;oldestMessageWithLowestPriorityEvictionStrategy/&gt;
+</div></div><p>where <strong><code>propertyName</code></strong> is the JMS message property that specifies the price.</p><p>Another option could be to use the oldest message with the lowest priority message. Therefore if you have some high priority messages, evict the lower priority messages first even if they are newer.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;oldestMessageWithLowestPriorityEvictionStrategy/&gt;
 </pre>
-</div></div><h2 id="SlowConsumerHandling-Example">Example</h2><p>The following example shows an ActiveMQ broker configuration file. Notice that for topics in the <strong>PRICES.&gt;</strong> wildcard range the <strong>pendingMessageLimitStrategy</strong> property is set to only keep around 10 messages for each consumer above their prefetch buffer size.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;beans 
-  xmlns="http://www.springframework.org/schema/beans" 
-  xmlns:amq="http://activemq.apache.org/schema/core"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
-  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd"&gt;
+</div></div><h2 id="SlowConsumerHandling-Example">Example</h2><p>The following example shows an ActiveMQ broker configuration file. Notice that for topics in the <strong><code>PRICES.&gt;</code></strong> wildcard range the&#160;<strong><code>pendingMessageLimitStrategy</code></strong> property is set to only keep around&#160;<strong><code>10</code></strong> messages for each consumer above their prefetch buffer size.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;beans xmlns="http://www.springframework.org/schema/beans" 
+       xmlns:amq="http://activemq.apache.org/schema/core"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans 
+                           http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://activemq.apache.org/schema/core
+                          &#160;http://activemq.apache.org/schema/core/activemq-core.xsd"&gt;
+                           
   &lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/&gt;
-  &lt;broker persistent="false" brokerName="${brokername}" xmlns="http://activemq.apache.org/schema/core"&gt;
+  
+  &lt;broker xmlns="http://activemq.apache.org/schema/core" 
+          persistent="false" 
+          brokerName="${brokername}"&gt;
+          
     &lt;!--  lets define the dispatch policy --&gt;
     &lt;destinationPolicy&gt;
       &lt;policyMap&gt;
         &lt;policyEntries&gt;
+
           &lt;policyEntry topic="FOO.&gt;"&gt;
             &lt;dispatchPolicy&gt;
-              &lt;roundRobinDispatchPolicy /&gt;
+              &lt;roundRobinDispatchPolicy/&gt;
             &lt;/dispatchPolicy&gt;
             &lt;subscriptionRecoveryPolicy&gt;
-              &lt;lastImageSubscriptionRecoveryPolicy /&gt;
+              &lt;lastImageSubscriptionRecoveryPolicy/&gt;
             &lt;/subscriptionRecoveryPolicy&gt;
           &lt;/policyEntry&gt;
+          
           &lt;policyEntry topic="ORDERS.&gt;"&gt;
             &lt;dispatchPolicy&gt;
-              &lt;strictOrderDispatchPolicy /&gt;
+              &lt;strictOrderDispatchPolicy/&gt;
             &lt;/dispatchPolicy&gt;
+
             &lt;!--  1 minutes worth --&gt;
             &lt;subscriptionRecoveryPolicy&gt;
-              &lt;timedSubscriptionRecoveryPolicy recoverDuration="60000" /&gt;
+              &lt;timedSubscriptionRecoveryPolicy recoverDuration="60000"/&gt;
             &lt;/subscriptionRecoveryPolicy&gt;
           &lt;/policyEntry&gt;
+          
           &lt;policyEntry topic="PRICES.&gt;"&gt;
             &lt;!-- lets force old messages to be discarded for slow consumers --&gt;
             &lt;pendingMessageLimitStrategy&gt;
               &lt;constantPendingMessageLimitStrategy limit="10"/&gt;
             &lt;/pendingMessageLimitStrategy&gt;
+
             &lt;!--  10 seconds worth --&gt;
             &lt;subscriptionRecoveryPolicy&gt;
-              &lt;timedSubscriptionRecoveryPolicy recoverDuration="10000" /&gt;
+              &lt;timedSubscriptionRecoveryPolicy recoverDuration="10000"/&gt;
             &lt;/subscriptionRecoveryPolicy&gt;
-            
           &lt;/policyEntry&gt;
-          &lt;policyEntry tempTopic="true" advisoryForConsumed="true" /&gt;
-          &lt;policyEntry tempQueue="true" advisoryForConsumed="true" /&gt;
+          
+          &lt;policyEntry tempTopic="true" advisoryForConsumed="true"/&gt;
+          &lt;policyEntry tempQueue="true" advisoryForConsumed="true"/&gt;
+          
         &lt;/policyEntries&gt;
       &lt;/policyMap&gt;
     &lt;/destinationPolicy&gt;
   &lt;/broker&gt;
 &lt;/beans&gt;</pre>
-</div></div><h2 id="SlowConsumerHandling-Usagetips">Usage tips</h2><p>It is advisable that if you know a particular consumer is going to be slow then set its prefetch size to something smaller than the fast consumers. e.g. if you know a particular box is quite slow and you have very high message rates and you have some very fast consumers; you might want to enable this feature and set the prefetch on the slow boxes to a little lower than on the fast boxes.</p><h3 id="SlowConsumerHandling-Monitoringthestatusofslowconsumers">Monitoring the status of slow consumers</h3><p>You can also use a <a shape="rect" href="jmx.html">JMX</a> Console to view the statistics of the active subscriptions. This allows you to view the following statistics on a TopicSubscriptionViewMBean</p><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Statistic</p></th><th colspan="1" rowspan="1" class="confluenceTh"><p>Meaning</p></th></tr><tr><td c
 olspan="1" rowspan="1" class="confluenceTd"><p>discarded</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>The count of how many messages have been discarded during the lifetime of the subscription due to it being a slow consumer</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>matched</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>The current number of messages matched and to be dispatched to the subscription as soon as some capacity is available in the prefetch buffer. So a non-zero value implies that the prefetch buffer is full for this subscription</p></td></tr></tbody></table></div></div>
+</div></div><h2 id="SlowConsumerHandling-UsageTips">Usage Tips</h2><p>&#160;</p><div class="confluence-information-macro confluence-information-macro-tip"><span class="aui-icon aui-icon-small aui-iconfont-approve confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>It is advisable that if you know a particular consumer is going to be slow then set its prefetch size to something smaller than the fast consumers!</p><p>For example, if you know a particular server is quite slow and you have very high message rates<em> and</em> you have some very fast consumers then you might want to enable this feature and set the prefetch on the slow servers to be a <em>little</em> lower than on the fast servers.</p></div></div><h3 id="SlowConsumerHandling-MonitoringtheStatusofSlowConsumers">Monitoring the Status of Slow Consumers</h3><p>You can also use a <a shape="rect" href="jmx.html">JMX</a> Console to view the statistics of the active subscriptions. This allo
 ws you to view the following statistics on a <strong><code>TopicSubscriptionViewMBean</code></strong>:</p><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Statistic</p></th><th colspan="1" rowspan="1" class="confluenceTh"><p>Definition</p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><code>discarded</code></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>The count of how many messages have been discarded during the lifetime of the subscription due to it being a slow consumer</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><code>matched</code></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>The current number of messages matched and to be dispatched to the subscription as soon as some capacity is available in the prefetch buffer. So a non-zero value implies that the prefetch buffer is full for this subscription</p></td></tr></tbody></table></div></div>
         </td>
         <td valign="top">
           <div class="navigation">