Slow Consumer Disconnect - User Guide
Introduction
Slow Consumer Disconnect (SCD) is a new feature in Qpid that provides a configurable
mechanism to prevent a single slow consumer from causing a back up of unconsumed messages on
the broker.
This is most relevant where Topics are in use, since a published message is not removed
from the broker's memory until all subscribers have acknowledged that message.
Cases where a consumer is 'slow' can arise due to one of the following: poor network
connectivity exists; a transient system issue affects a single client; a single subscriber
written by a client team is behaving incorrectly and not acknowledging messages; a
downstream resource such as a database is non-responsive.
SCD will enable the application owner to configure limits for a given consumer's queue and
the behaviour to execute when those limits are reached.
What can it do?
SCD is only applicable to topics or durable subscriptions and can be configured on either
a topic or a subscription name.
On triggering of a specified threshold the offending client will be disconnected from the
broker with a 506 error code wrapped in a JMSException returned to the client via the
ExceptionListener registered on the Connection object.
Note that it is essential that an ExceptionListener be specified by the client on
creation of the connection and that exceptions coming back on that listener are handled
correctly.
Frequency of SCD Checking
Configuring Frequency
You can configure the frequency with which the SCD process will check for slow consumers,
along with the unit of time used to specify that frequency.
The virtualhosts.virtualhost.hostname.slow-consumer-detection
elements delay and timeunit
are used to specify the frequency and timeunit respectively in the virtualhosts.xml
file e.g.
<virtualhosts>
<default>test</default>
<virtualhost>
<name>test</name>
<test>
<slow-consumer-detection>
<delay>60<delay/>
<timeunit>seconds<timeunit/>
<slow-consumer-detection/>
</test>
</virtualhost>
</virtualhosts>
SCD Log output
When the SCD component finds a queue with a configured threshold to check, the operational
logging component (if enabled) will output the following line:
SCD-1003 : Checking Status of Queue
Client Exceptions
When a Slow Consumer is disconnected, the client receives a 506 error from the broker
wrapped in a JMSException and the Session and Connection are closed:
Dispatcher-Channel-1 2010-09-01 16:23:34,206 INFO [qpid.client.AMQSession.Dispatcher]
Dispatcher-Channel-1 thread terminating for channel 1:org.apache.qpid.client.AMQSession_0_8@1de8aa8
pool-2-thread-3 2010-09-01 16:23:34,238 INFO [apache.qpid.client.AMQConnection] Closing AMQConnection due to
:org.apache.qpid.AMQChannelClosedException: Error: Consuming to slow. [error code 506: resource error]
javax.jms.JMSException: 506
at org.apache.qpid.client.AMQConnection.exceptionReceived(AMQConnection.java:1396)
at org.apache.qpid.client.protocol.AMQProtocolHandler.exception(AMQProtocolHandler.java:329)
at org.apache.qpid.client.protocol.AMQProtocolHandler.methodBodyReceived(AMQProtocolHandler.java:536)
at org.apache.qpid.client.protocol.AMQProtocolSession.methodFrameReceived(AMQProtocolSession.java:453)
at org.apache.qpid.framing.AMQMethodBodyImpl.handle(AMQMethodBodyImpl.java:93)
at org.apache.qpid.client.protocol.AMQProtocolHandler$1.run(AMQProtocolHandler.java:462)
at org.apache.qpid.pool.Job.processAll(Job.java:110)
at org.apache.qpid.pool.Job.run(Job.java:149)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.apache.qpid.AMQChannelClosedException: Error: Consuming to slow. [error code 506: resource error]
at org.apache.qpid.client.handler.ChannelCloseMethodHandler.methodReceived(ChannelCloseMethodHandler.java:96)
at org.apache.qpid.client.handler.ClientMethodDispatcherImpl.dispatchChannelClose(ClientMethodDispatcherImpl.java:163)
at org.apache.qpid.framing.amqp_8_0.ChannelCloseBodyImpl.execute(ChannelCloseBodyImpl.java:140)
at org.apache.qpid.client.state.AMQStateManager.methodReceived(AMQStateManager.java:112)
at org.apache.qpid.client.protocol.AMQProtocolHandler.methodBodyReceived(AMQProtocolHandler.java:511)
... 8 more
main 2010-09-01 16:23:34,316 INFO [apache.qpid.client.AMQSession] Closing session:
org.apache.qpid.client.AMQSession_0_8@ffeef1
Disconnection Thresholds
Topic Subscriptions
One key feature of SCD is the disconnection of a consuming client when a specified
threshold is exceeded. For a pub-sub model using topics, this means that messages will no
longer be delivered to the private queue which was associated with that consuming client,
thus reducing any associated backlog in the broker.
Durable Topic Subscriptions
For durable subscriptions, simply disconnecting the consuming client will not suffice
since the associated queue is by definition durable and messages would continue to flow to
it after disconnection, potentially worsening any backing up of data on the broker.
The solution is to configure durable subscriptions to delete the underlying queue on
disconnection. This means that messages will no longer be delivered to the private queue
associated with the subscription, thus preventing any backlog.
Full details of how to configure the thresholds are provided below.
Message Age Threshold
You can configure SCD to be triggered on a topic or subscription when the oldest message
in the associated private queue for the consumer ages beyond the specified value, in
milliseconds.
Queue Depth Threshold
You can opt to use the depth of the queue in bytes as a threshold. SCD will be triggered
by a queue depth greater than the threshold specified i.e. when a broker receives a
message that takes the queue depth over the threshold.
Message Count Threshold
You can use the message count for the consumer's queue as the trigger, where a count
higher than that specified will trigger disconnection.
Delete Policy
You can configure the policy you wish to apply in your broker configuration. There are
currently 2 policies available:
Delete Temporary Queues Only
If you do not specify a <topicDelete/> element in your configuration, then only temporary
queues associated with a topic subscription will be deleted on client disconnect. This is
the default behaviour.
Delete Durable Subscription Queues
If you add the <topicDelete/> element with the sub-element
<delete-persistent/> to your config, then the persistent queue which is associated
with durable subscriptions to a topic will also be deleted. This is an important
consideration since without deleting the underlying queue the client's unconsumed data
will grow indefinitely while they will be unable to reconnect to that queue due to the SCD
threshold configured, potentially having an adverse effect on the application or broker in
use.
Example Topic Configuration
The following steps are required to configure SCD:
Enable SCD checking for your virtual host
Specify frequency for SCD checking
Define thresholds for the topic
Define the policy to apply on trigger
The example below shows a simple definition, with all three thresholds specified and a
simple disconnection, with deletion of any temporary queue, defined.
For a durable subscription to this topic, no queue deletion would be applied on disconnect
- which is likely to be undesirable (see section above).
<topics>
<topic>
<name>stocks.us.*</name>
<slow-consumer-detection>
<!-- The maximum depth before which -->
<!-- the policy will be applied-->
<depth>4235264</depth>
<!-- The maximum message age before which -->
<!-- the policy will be applied-->
<messageAge>600000</messageAge>
<!-- The maximum number of message before -->
<!-- which the policy will be applied-->
<messageCount>50</messageCount>
<!-- Policy Selection -->
<policy name="TopicDelete"/>
</slow-consumer-detection>
</topic>
</topics>
Important Points To Note
Client application developers should be educated about how to correctly handle being
disconnected with a 506 error code, to avoid them getting into a thrashing state where they
continually attempt to connect, fail to consume fast enough and are disconnected again.
Clients affected by slow consumer disconnect configuration should always use transactions
where duplicate processing of an incoming message would have adverse affects, since they may
receive a message more than once if disconnected before acknowledging a message in flight.