Using RabbitMQ in a cluster

Component: RabbitMQ Transport
NuGet Package NServiceBus.RabbitMQ (7-pre)
Target NServiceBus Version: 8.x
This page targets a pre-release version. Pre-releases are subject to change and samples are not guaranteed to be fully functional.

The RabbitMQ Clustering Guide recommends that client applications should not hard-code the hostnames or IP addresses of the machines hosting nodes in a RabbitMQ cluster. An approach such as DNS or load balancing should be used instead. This approach is recommended when using the NServiceBus RabbitMQ transport.

If each client is deployed to a machine which is running at least one RabbitMQ node in the cluster, another approach is to configure the client to only connect to the local node, e.g. using localhost as the hostname. Note that the RabbitMQ nodes must still be clustered, otherwise clients on each machine will have access only to the messages which originated locally.

Connecting to additional nodes

Nodes within a cluster can be specified by providing the host and port details to the AddClusterNode method of the base RabbitMQClusterTransport class. When multiple nodes have been specified, the RabbitMQ connection factory will choose a node at random to connect to. This occurs during reconnection scenarios too.

RabbitMQ has a concept of a single master queue and this can result in unnecessary network hops. See load balancing a rabbitmq cluster.

Quorum queues

Starting with RabbitMQ version 3.8.0, quorum queues are an alternative to mirrored queues when data safety is a high priority.

The input queue for an endpoint can be created as a quorum queue using the QueueMode.Quorum setting with the RabbitMQClusterTransport:

var rabbitMqTransport = new RabbitMQClusterTransport(Topology.Conventional, "host=localhost", QueueMode.Quorum, DelayedDeliverySupport.Disabled);
endpointConfiguration.UseTransport(rabbitMqTransport);
An existing queue cannot be automatically converted to a quorum queue. Endpoints are not able to detect a queue-mode configuration mismatch on existing queues and will ignore the configured queue mode when the queue already exists.
Quorum queues do not support time-to-be-received. Messages with a time-to-be-received configured won't be discarded if the destination is a quorum queue.
Endpoints must be updated to NServiceBus.Transport.RabbitMQ version 6.1 or higher in order to send messages to endpoints using quorum queues or to shared error and audit queues that are configured as quorum queues.

Delayed delivery

The delayed delivery infrastructure provided by the RabbitMQ transport is not supported by quorum queues. The delayed delivery infrastructure continues to use classic queues and dead letter exchanges which can be exposed to message loss in a RabbitMQ cluster. Therefore, it is recommended to disable delayed delivery features (e.g. saga timeouts, delayed retries, and delayed messages) by using the DelayedDeliverySupport.Disabled option when configuring the transport:

var rabbitMqTransport = new RabbitMQClusterTransport(Topology.Conventional, "host=localhost", QueueMode.Classic, DelayedDeliverySupport.Disabled);
endpointConfiguration.UseTransport(rabbitMqTransport);

// delayed retries are enabled by default and need to be explicitly disabled:
endpointConfiguration.Recoverability().Delayed(c => c.NumberOfRetries(0));

To enable delayed delivery regardless of the risk of message loss, configure the DelayedDeliverySupport.UnsafeEnabled option:

var rabbitMqTransport = new RabbitMQClusterTransport(Topology.Conventional, "host=localhost", QueueMode.Classic, DelayedDeliverySupport.UnsafeEnabled);
endpointConfiguration.UseTransport(rabbitMqTransport);

Related Articles


Last modified