Using EventingBasicConsumer in C# causes Unack'd messages

1,125 views
Skip to first unread message

Marty Wasznicky

unread,
Dec 21, 2015, 10:54:49 PM12/21/15
to rabbitmq-users
I'm currently using EventingBasicConsumer in the .NET client library, 3.5.4
However, I'm getting unreliable results when I disconnect the channel and connection and then wire it back up.

For example, the first time I connect, I create a connection, than the IModel channel.  From there, I create the EventingBasicConsumer and wire in the received event like so:

            _consumer = new EventingBasicConsumer(_consumerChannel);

            var consumerTag = _consumerChannel.BasicConsume(this.queueName, false, _consumer);

            _consumer.ConsumerCancelled += consumer_ConsumerCancelled;
            _consumer.Shutdown += consumer_Shutdown;
            _consumer.Received += consumer_Received;


I'll publish a few messages which the consumer_Received will receive just fine.

I'll then disconnect the consumer by doing the following :

           if (null != _consumer)
            {
                _consumer.ConsumerCancelled -= consumer_ConsumerCancelled;
                _consumer.Shutdown -= consumer_Shutdown;
                _consumer.Received -= consumer_Received;
                _consumer = null;
            }


Marty Wasznicky

unread,
Dec 21, 2015, 11:00:41 PM12/21/15
to rabbitmq-users
sorry....this posted before I finished.  After I clean up the consumer, I clean up the model and connection like so:

          try
            {
                if (null != _consumerChannel)
                {
                    _consumerChannel.FlowControl -= this.FlowControlChanged;
                    _consumerChannel.Close();
                }
            }
            catch
            {
                try
                {
                    _consumerChannel.Abort();
                }
                catch { }
            }
            finally
            {
                try
                {
                    if (null != _consumerChannel)
                    {
                        _consumerChannel.Dispose();
                    }
                }
                catch { }
                finally
                {
                    _consumerChannel = null;
                }
            } 

if (null != this.connection)
            {
                try
                {
                    this.connection.ConnectionBlocked -= this.ConnectionOnConnectionBlocked;
                    this.connection.ConnectionUnblocked -= this.ConnectionOnConnectionUnBlocked;
                    this.connection.ConnectionShutdown -= this.ConnectionOnConnectionShutdown;
                    this.connection.Close(1000);
                }
                catch
                {
                    try
                    {
                        this.connection.Abort();
                    }
                    catch { }
                }
                finally
                {
                    if (null != connection)
                    {
                        // yes...just calling dispose can cause a System.IO.IOException....
                        try
                        {
                            connection.Dispose();
                        }
                        catch { }
                        finally
                        {
                            connection = null;
                        }
                    }
                }
            }



so far all good, right?

after this, I will publish another message.  Once the message is published (this is done in a separate app using a separate connection object), I'll go ahead and reconnect my consumer.

everything will be created from scratch again...the connection, the IModel channel and then the event consumer at which point I'll wire in the received event again.  However, now NO messages will be received.

If I look at the rabbitMQ health monitor, I can see that I'm connected to the Queue (i.e. 1 consumer is registered) however, there is 1 unacked message....and its stuck.

Here's the rub.  If I go through the process and disconnect my event consumer again (exact same way as I showed above), I'll now get the message.

What's happening here?  How do I go about troubleshooting this?  is the event consumer somehow NOT getting properly unregistered?

any help would be Greatly appreciated.

Thanks!

Marty Wasznicky

unread,
Dec 22, 2015, 12:28:43 AM12/22/15
to rabbitmq-users
just tried adding this as the last line when I'm cleaning up the consumer:

if (!string.IsNullOrEmpty(consumerTag)) _consumer.Model.BasicCancel(consumerTag);

however, didn't change the behavior I'm seeing 

Michael Klishin

unread,
Dec 22, 2015, 12:33:47 PM12/22/15
to rabbitm...@googlegroups.com, Marty Wasznicky
 On 22 December 2015 at 07:00:44, Marty Wasznicky (marty...@gmail.com) wrote:
> after this, I will publish another message. Once the message
> is published (this is done in a separate app using a separate connection
> object), I'll go ahead and reconnect my consumer.
>
> everything will be created from scratch again...the connection,
> the IModel channel and then the event consumer at which point
> I'll wire in the received event again. However, now NO messages
> will be received.
>
> If I look at the rabbitMQ health monitor, I can see that I'm connected
> to the Queue (i.e. 1 consumer is registered) however, there is
> 1 unacked message....and its stuck.
>
> Here's the rub. If I go through the process and disconnect my event
> consumer again (exact same way as I showed above), I'll now get
> the message.
>
> What's happening here? How do I go about troubleshooting this?
> is the event consumer somehow NOT getting properly unregistered?

You are not being very specific what "reconnect" and "disconnect" means in this case
but if you drop TCP traffic, that takes time for both peers to notice.

See http://rabbitmq.com/heartbeats.html. A value between 6-15 seconds is recommended.

Unacknowledged messages can also mean you have channels or entire connections
around that are not closed when you expect them to be. For example, the correct way to do it is
via IConnection and IModel.Close, not .Dispose.
--
MK

Staff Software Engineer, Pivotal/RabbitMQ


Matt Gathman

unread,
Oct 29, 2018, 6:02:37 PM10/29/18
to rabbitmq-users
Hey guys, 

I know this is pretty old, but I was running into the same issue.
I eventually figured out it was because I wasn't setting my eventhandler on the consumer until after registering it via basic consume.

My guess is this created a window where a message could be delivered but have no event handler to actually Ack it.

After switching my code around to set the handler prior to calling BasicConsume, the issue went away.

Michael Klishin

unread,
Oct 29, 2018, 7:26:43 PM10/29/18
to rabbitm...@googlegroups.com
Hi Matt,

Your understanding is correct. We will try to make this explicit in the docs.
Also, this is applicable to all clients since the root cause is a natural race condition.

Thank you for reporting back to the list!

Cheers.
--
You received this message because you are subscribed to the Google Groups "rabbitmq-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rabbitmq-user...@googlegroups.com.
To post to this group, send email to rabbitm...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages