| <?xml version="1.0" encoding="utf-8"?> |
| <!DOCTYPE entities [ |
| <!ENTITY % entities SYSTEM "commonEntities.xml"> |
| %entities; |
| ]> |
| <!-- |
| |
| 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. |
| |
| --> |
| |
| <section id="Java-Broker-Runtime-Handling-Undeliverable-Messages"> |
| <title>Handing Undeliverable Messages</title> |
| |
| <section role="h2" id="Java-Broker-Runtime-Handling-Undeliverable-Messages-Introduction"> |
| <title>Introduction</title> |
| <para> Messages that cannot be delivered successfully to a consumer (for instance, because the |
| client is using a transacted session and rolls-back the transaction) can be made available on |
| the queue again and then subsequently be redelivered, depending on the precise session |
| acknowledgement mode and messaging model used by the application. This is normally desirable |
| behaviour that contributes to the ability of a system to withstand unexpected errors. However, it |
| leaves open the possibility for a message to be repeatedly redelivered (potentially indefinitely), |
| consuming system resources and preventing the delivery of other messages. Such undeliverable |
| messages are sometimes known as poison messages.</para> |
| <para>For an example, consider a stock ticker application that has been designed to consume prices |
| contained within JMS TextMessages. What if inadvertently a BytesMessage is placed onto the queue? |
| As the ticker application does not expect the BytesMessage, its processing might fail and cause it |
| to roll-back the transaction, however the default behavior of the Broker would mean that the |
| BytesMessage would be delivered over and over again, preventing the delivery of other legitimate |
| messages, until an operator intervenes and removes the erroneous message from the queue. </para> |
| <para>Qpid has maximum delivery count and dead-letter queue (DLQ) features which can be used in |
| concert to construct a system that automatically handles such a condition. These features are |
| described in the following sections.</para> |
| </section> |
| |
| <section role="h2" id="Java-Broker-Runtime-Handling-Undeliverable-Messages-Maximum-Delivery-Count"> |
| <title>Maximum Delivery Count</title> |
| <para> Maximum delivery count is a property of a queue. If a consumer application is unable to |
| process a message more than the specified number of times, then the broker will either route the |
| message to a dead-letter queue (if one has been defined), or will discard the message. </para> |
| <para> In order for a maximum delivery count to be enforced, the consuming client |
| <emphasis>must</emphasis> call <ulink url="&oracleJeeDocUrl;javax/jms/Session.html#rollback()" |
| >Session#rollback()</ulink> (or <ulink url="&oracleJeeDocUrl;javax/jms/Session.html#recover()" |
| >Session#recover()</ulink> if the session is not transacted). It is during the Broker's |
| processing of Session#rollback() (or Session#recover()) that if a message has been seen |
| at least the maximum number of times then it will move the message to the DLQ or discard the |
| message.</para> |
| <para>If the consuming client fails in another manner, for instance, closes the connection, the |
| message will not be re-routed and consumer application will see the same poison message again |
| once it reconnects.</para> |
| <para> If the consuming application is using AMQP 0-9-1, 0-9, or 0-8 protocols, it is necessary to |
| set the client system property <varname>qpid.reject.behaviour</varname> or connection or binding |
| URL option <varname>rejectbehaviour</varname> to the value <literal>system</literal>.</para> |
| <para>It is possible to determine the number of times a message has been sent to a consumer via |
| the Management interfaces, but is not possible to determine this information from a message client. |
| Specifically, the optional JMS message header <property>JMSXDeliveryCount</property> is not |
| supported.</para> |
| <para>Maximum Delivery Count can be enabled via management (see <xref |
| linkend="Java-Broker-Configuring-And-Managing"/>) using the the queue declare property |
| <property>x-qpid-maximum-delivery-count</property> or via <link |
| linkend="Java-Broker-Runtime-Handling-Undeliverable-Messages-Configuration">configuration</link> |
| as illustrated below.</para> |
| </section> |
| |
| <section role="h2" id="Java-Broker-Runtime-Handling-Undeliverable-Messages-Dead-Letter-Queues"> |
| <title>Dead Letter Queues (DLQ)</title> |
| <para>A Dead Letter Queue (DLQ) acts as an destination for messages that have somehow exceeded the |
| normal bounds of processing and is utilised to prevent disruption to flow of other messages. When |
| a DLQ is enabled for a given queue if a consuming client indicates it no longer wishes the |
| receive the message (typically by exceeding a Maximum Delivery Count) then the message is moved |
| onto the DLQ and removed from the original queue. </para> |
| <para>The DLQ feature causes generation of a Dead Letter Exchange and a Dead Letter Queue. These |
| are named convention QueueName<emphasis>_DLE</emphasis> and QueueName<emphasis>_DLQ</emphasis>.</para> |
| <para>DLQs can be enabled via management (see <xref linkend="Java-Broker-Configuring-And-Managing" |
| />) using the queue declare property <property>x-qpid-dlq-enabled</property> or via <link |
| linkend="Java-Broker-Runtime-Handling-Undeliverable-Messages-Configuration">configuration</link> |
| as illustrated below.</para> |
| <caution> |
| <title>Avoid excessive queue depth</title> |
| <para>Applications making use of DLQs <emphasis>should</emphasis> make provision for the frequent |
| examination of messages arriving on DLQs so that both corrective actions can be taken to resolve |
| the underlying cause and organise for their timely removal from the DLQ. Messages on DLQs |
| consume system resources in the same manner as messages on normal queues so excessive queue |
| depths should not be permitted to develop.</para> |
| </caution> |
| </section> |
| |
| <section role="h2" id="Java-Broker-Runtime-Handling-Undeliverable-Messages-Configuration"> |
| <title>Configuration</title> |
| <para>In the below configuration it can be seen that DLQs/Maximum Delivery Count are enabled at |
| the broker level with maximum delivery count set to 5, disabled at the virtualhost level for the |
| 'dev-only' virtualhost, and enabled specifically for the 'dev-only-main-queue' with maximum |
| delivery count overridden to 5. </para> |
| <para>As 'dev-only-main-queue' has its own configuration specified, this value overrides all |
| others and causes the features to be enabled for this queue. In contrast to this, |
| 'dev-only-other-queue' does not specify its own value and picks up the false value specified for |
| its parent virtualhost, causing the DLQ/Maximum Delivery Count features to be disabled for this |
| queue. Any such queue in the 'dev-only' virtualhost which does not specify its own configuration |
| value will have the DLQ/Maximum Delivery Count feature disabled.</para> |
| <para>The queue 'localhost-queue' has the DLQ/Maximum Delivery Count features enabled, as neither |
| the queue itself or the 'localhost' virtualhost specifies a configuration value and so the broker |
| level value of true is used. Any such queue in the 'localhost' virtualhost which does not specify |
| its own configuration value will have the features enabled.</para> |
| <example> |
| <title>Enabling DLQs and maximum delivery count at broker level within config.xml</title> |
| <programlisting><![CDATA[<broker> |
| ... |
| <deadLetterQueues>true</deadLetterQueues> |
| <maximumDeliveryCount>5</maximumDeliveryCount> |
| ... |
| </broker>]]></programlisting> |
| </example> |
| <example> |
| <title>Enabling DLQs and maximum delivery count at virtualhost and queue level within |
| virtualhosts.xml</title> |
| <programlisting><![CDATA[<virtualhosts> |
| ... |
| <virtualhost> |
| <name>dev-only</name> |
| <dev-only> |
| <queues> |
| <deadLetterQueues>false</deadLetterQueues> |
| <maximumDeliveryCount>0</maximumDeliveryCount> |
| <queue> |
| <name>dev-only-main-queue</name> |
| <dev-only-main-queue> |
| <deadLetterQueues>true</deadLetterQueues> |
| <maximumDeliveryCount>3</maximumDeliveryCount> |
| </dev-only-main-queue> |
| </queue> |
| <queue> |
| <name>dev-only-other-queue</name> |
| </queue> |
| </queues> |
| </dev-only> |
| </virtualhost> |
| <virtualhost> |
| <name>localhost</name> |
| <localhost> |
| <queues> |
| <queue> |
| <name>localhost-queue</name> |
| </queue> |
| </queues> |
| </localhost> |
| </virtualhost> |
| ... |
| </virtualhosts>]]> |
| </programlisting> |
| </example> |
| </section> |
| |
| |
| </section> |