[prev in list] [next in list] [prev in thread] [next in thread] 

List:       activemq-dev
Subject:    [jira] [Created] (AMQ-4151) Duplicate non-persistent messages that are sent to a queue are either di
From:       "Stirling Chow (JIRA)" <jira () apache ! org>
Date:       2012-10-31 23:21:11
Message-ID: 493500818.53679.1351725672177.JavaMail.jiratomcat () arcas
[Download RAW message or body]

Stirling Chow created AMQ-4151:
----------------------------------

             Summary: Duplicate non-persistent messages that are sent to a queue are \
either dispatched multiple times (i.e., not detected as duplicates) or cause the \
queue size to be miscalculated.  Key: AMQ-4151
                 URL: https://issues.apache.org/jira/browse/AMQ-4151
             Project: ActiveMQ
          Issue Type: Bug
            Reporter: Stirling Chow


Symptom
=======
We have a virtual topic that is shared by a network of brokers.  Each broker has \
consumers that process the corresponding Consumer.*.VirtualTopic.> queue.

While testing the effects of memory limits on our system, we encountered AMQ-4148, \
which resulted in duplicate subscriptions being made to the virtual topic.  These \
duplicate subcriptions were attempting to enqueue the same topic message multiple \
times to the corresponding Consumer.*.VirtualTopic.>.

Although logic exists in queues to handle duplicate messages, we noticed lots of \
strange behaviour with duplicate handling.  We decided to investigate further and \
found a race condition whereby duplicate non-persistent messages that were correctly \
ignored resulted in the queue size appearing to be non-empty when in fact there were \
no messages.

While our original investigation was prompted by AMQ-4148, the test case we attached \
to this ticket does not rely on the misbehaviour caused by AMQ-4148, but can occur \
during normal operation of network bridges when there are multiple consumers for a \
virtual topic (as is the case, e.g., when conduit subscriptions are disabled).

Cause
=====
If a virtual topic has multiple consumers, then sending a message to the topic \
results in multiple dispatches of the same message (one to each consumer).  If the \
multiple consumers originate from the same remote broker (e.g., because conduit \
subscriptions are disabled), then a single message sent to the virtual topic on \
broker1 will result in multiple duplicate messages being sent to the virtual topic on \
broker2.

If broker2 has corresponding Consumer.*.VirtualTopic.> queue, then the multiple \
duplicate messages sent to the virtual topic on broker2 will result in multiple \
duplicate messages being sent to the queue.  

If the messages are non-persistent, the only logic that prevents each duplicate \
message from being dispatched to a consumer is as follows:

{code:title=Queue.java}
private PendingList doPageInForDispatch(boolean force) throws Exception {
...
        // Only add new messages, not already pagedIn to avoid multiple
        // dispatch attempts
        pagedInMessagesLock.writeLock().lock();
        try {
            if(isPrioritizedMessages()) {
                resultList = new PrioritizedPendingList();
            } else {
                resultList = new OrderedPendingList();
            }
            for (QueueMessageReference ref : result) {
                if (!pagedInMessages.containsKey(ref.getMessageId())) {
                    pagedInMessages.put(ref.getMessageId(), ref);
                    resultList.addMessageLast(ref);
                } else {
                    ref.decrementReferenceCount();
                }
            }
        } finally {
            pagedInMessagesLock.writeLock().unlock();
        }
...        
{code}

If the consumers are fast and acknowledge the initial message dispatch before the \
next duplicate message is sent to the queue, then the \
{{pagedInMessages.constainsKey(...)}} check will *not* prevent the duplicate message \
from being dispatched since the message ID will have already been removed as part of \
the acknowledgement.

This is problem 1: duplicate detection fails if acknowledgements are quick

If the consumers are slow and don't acknowledge the initial message dispatch before \
the next duplicate message is sent to the queue, then duplicate detection will \
correctly ignore the message.  However, by this time, the duplicate message has \
already incremented the queue size:

{code:title=Queue.java}
final void messageSent(final ConnectionContext context, final Message msg) throws \
Exception {  destinationStatistics.getEnqueues().increment();
    destinationStatistics.getMessages().increment();
    messageDelivered(context, msg);
{code}

The call to {{messageSent}} is made by the thread sending the message to the queue.  \
This thread is completely unaware that the message was ignored since the call to \
{{doPageInForDispatch}} is done by a separate thread (e.g., the taskrunner calling \
{{iterate()}}.

Since the queue size is incremented, but the duplicate message is never dispatched, \
there is no subsequent acknowledgement ot reduce the queue size.  As a result, each \
duplicate message that is ignored remains counted in the queue size even though it's \
no longer in the queue.  

This is problem 2: if duplication detection succeeds, the queue size incorrectly \
counts the duplicate/ignored message.

Which problem gets exhibited depends on a race condition between the thread(s) \
enqueueing the duplicate virtual topic subscriptions and consumer threads \
acknowledging the dispatches.

While the unit test's methodology of creating multiple virtual topic consumers is \
somewhat contrived, there must be other circumstances under which duplicate messages \
are sent to queues (otherwise, why would there be logic to handle this case?)  In \
this context, the test case reveals a problem with the handling of duplicate \
messages.

Solution
========
None at this time.  We worked around the problem by patching AMQ-4148 to prevent the \
duplicate subscriptions that cause this bug.  However, our concern has been raised \
about AMQ's generally handling of duplicate messages sent to a queue.





--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic