4

I have 2 RabbitMQ clusters in separate datacenters. At the moment we are shovelling one of the exchanges from an one rabbit to the other but now we need to shovel in the other direction too. How can we achieve this without causing an infinite loop?

A colleague thought we could tick the "Add Forwarding Headers" options and then filter using a Header exchange. However, the headers that get added appear to be nested and I've not found a way to match against the headers?

Tom
  • 2,416
  • 3
  • 31
  • 38
  • Could you provide more context regarding your use case? Is there some reasons you selected shovel vs [federation](https://www.rabbitmq.com/federation-reference.html)? – Olivier Apr 27 '18 at 08:26
  • Only that we are already using shovel and familiar with it. Not really familiar with federation, I shall examine. Essentially we have a rabbit in each datacenter each with a producer writing to exchange with the same name. We then have queues bound to those exchanges and we need those queues to have all messages from both producers. so we need to replicate both ways but need to avoid replicating the already replicated messages. – Tom Apr 27 '18 at 16:17

1 Answers1

2

Seems based on the additional description you provided that:

  • You are using shovel between exchanges
  • Guessing that the exchange type is fanout

I can see two approaches to handle what you're trying to do:

  • Use federation, and configure it in both directions between the exchanges in each cluster
  • Still use shovel, but define a new queue on each exchange and configure a queue to queue shovel

For the shovel option: You have exchange A on cluster 1, exchange A on cluster 2, your main_queue on each cluster

  • Create a secondary_queue on each cluster, bound to exchange A.
  • Create a shovel from secondary queue on cluster 1 to main_queue on cluster 2
  • Create a shovel from secondary queue on cluster 2 to main_queue on cluster 1

Benefit of Federation: simpler, even when you have complex routing configured

Benefit of shovel: better if you have risk of major connection disruption (more than a minute I'd say). In such cases you won't lose messages while it might happen in the Federation case that some messages don't get replicated on both clusters.

Olivier
  • 2,571
  • 1
  • 17
  • 25
  • Hi Olivier - thanks for your answer. Your shovel solution looks interesting but when I said queues bound, I meant multiple queues as there are several applications that need all the messages. Thinking about it though, I guess that could be an exchange with the queues following it. The downside is that it would require changes to existing producer applications. I shall definitely investigate federation but concerned about the potential loss of messages. Still very keen to hear a solution that uses the exchange header matching. Are you familiar with this? – Tom Apr 30 '18 at 09:03
  • Hi @Tom, I'm a fair user of RabbitMQ, so although I'm hopeful the comments I make can help you, I'm nowhere near expert level. Taking that into consideration, I'd definetely recommend looking into federation as it seems from some additional reading that it's possible to have it tolerate serious disconnects with some parameters. Regarding the headers exchange, I haven't had a use for them, although I know their logic. Finally it's difficult to make a "good" recommendation without additional details on your setup, specifically the type of exchanges you are using, and the number of queues. – Olivier Apr 30 '18 at 11:32
  • Ended up using a variation of your secondary queue approach that introduced a second level of exchanges and created a queue hanging off the upper level exchange shovelling to the lower level exchange on the other broker. – Tom Dec 18 '18 at 16:12
  • @Tom I need to do the same. Can you elaborate your solution a little more? – qdivision Jun 14 '22 at 17:35
  • 1
    Eventually we did it such that we created a separate queue and shovel for each exchange (we only had 2) that sent the messages to a different exchange on the opposite side and then the downstream queues were bound to each exchange. So starting with 2 independent rabbits a and b with: EXa -> Qa -> CONSUMERa EXb -> Qb -> CONSUMERb EXa -> Qa -> CONSUMERa -> QshovelA -> SHOVEL -> EXfromA -> Qb -> CONSUMERb EXb -> Qb -> CONSUMERb -> QshovelB -> SHOVEL -> EXfromB -> Qa -> CONSUMERa – Tom Jun 15 '22 at 16:44
  • So Qa receives messages from ExA and ExfromB and Qb receives messages from ExB and ExfromA – Tom Jun 15 '22 at 16:45
  • This approach required no changes to publisher or consumer applications which was advantageous to us. – Tom Jun 15 '22 at 16:46