Skip to content
This repository was archived by the owner on Nov 17, 2023. It is now read-only.
This repository was archived by the owner on Nov 17, 2023. It is now read-only.

RabbitMQ queue bindings are lost after a reconnection #1701

@alan0428a

Description

@alan0428a

Hello there,

I was checking the auto-reconnect mechanism of RabbitMQ. Then I found that after a reconnection to RabbitMQ, the exchange and all queues are restored but the bindings between them are lost.
image

After carefully tracing the code and the RabbitMQ document, I think I might have the idea. The document states that

The following steps are performed for every channel known to being open at the time of connection failure:

  • Re-declare exchanges (except for predefined ones)
  • Re-declare queues
  • Recover all bindings
  • Recover all consumers

It means that if we want the bindings to be recovered after reconnection, channels must be opened at the time of connection failure. But in the DoInternalSubscription method, we use "using" to declare a channel, so the channel is being disposed when leaving the "using" section.

        private void DoInternalSubscription(string eventName)
        {
            var containsKey = _subsManager.HasSubscriptionsForEvent(eventName);
            if (!containsKey)
            {
                if (!_persistentConnection.IsConnected)
                {
                    _persistentConnection.TryConnect();
                }

                using (var channel = _persistentConnection.CreateModel())
                {
                    channel.QueueBind(queue: _queueName,
                                      exchange: BROKER_NAME,
                                      routingKey: eventName);
                }
            }
        }

Maybe we can use the _consumerChannel which is created at the constructor instead, rather than declare a new channel whenever needs to bind a queue to an exchange? What do you think?

The document also states that

Much like connections, channels are meant to be long lived. That is, there is no need to open a channel per operation and doing so would be very inefficient, since opening a channel is a network roundtrip.

So I think the fix might also improve the performance as well?

I have tested the approach and it works without issue. I am happy to create a PR if needed :)

How to reproduce

  1. Launch the project using docker-compose ( I was using visual studio)
  2. Stop the RabbitMQ container
  3. Wait services start trying to reconnect
  4. Start the RabbitMQ container
  5. Go to RabbitMQ admin UI to check bindings

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions