[Questions] Technique for introducing alternate exchanges to existing topologies #12402
-
Community Support Policy
RabbitMQ version used3.13.7 Erlang version used26.2.x Operating system (distribution) useddocker image How is RabbitMQ deployed?Community Docker image rabbitmq-diagnostics status outputSee https://www.rabbitmq.com/docs/cli to learn how to use rabbitmq-diagnostics Logs from node 1 (with sensitive values edited out)See https://www.rabbitmq.com/docs/logging to learn how to collect logs Logs from node 2 (if applicable, with sensitive values edited out)See https://www.rabbitmq.com/docs/logging to learn how to collect logs Logs from node 3 (if applicable, with sensitive values edited out)See https://www.rabbitmq.com/docs/logging to learn how to collect logs rabbitmq.confSee https://www.rabbitmq.com/docs/configure#config-location to learn how to find rabbitmq.conf file location Steps to deploy RabbitMQ clustertested on single docker container Steps to reproduce the behavior in questionWe are looking to introduce alternate exchanges to our existing topologies. Since we can't modify existing exchanges, then we need to create new exchanges with the alternate exchange configured. This makes sense, so we did the following: ---
title: exchange topology
---
flowchart LR
a[A]
b[B]
bAlt[AltB]
a-- Exchange to exchange binding with # ---b
b-- alternate exchange ---bAlt
This works great because the old publishers (A) and the new publishers (B) will both flow to exchange B and Rabbit dedupes any consumers with multiple bindings to both exchanges. However, we realized that new publishers wouldn't get messages back to old consumers that haven't be updated, so we added another exchange to exchange binding: flowchart LR
a[A]
b[B]
bAlt[AltB]
a-- Exchange to exchange binding with # ---b
b-- Exchange to exchange binding with # ---a
b-- alternate exchange ---bAlt
Surprisingly this works for routable message delivery (feels dirty). Old and new publishers' messages can be seen by old consumers. However, this seems to break the alternate exchange configuration as any unroutable messages are just that, unroutable and don't make it to AltB. Are we thinking about this wrong? (bidirectional e2e binding for migration, or is there a better way to phase out the old exchange?) advanced.configSee https://www.rabbitmq.com/docs/configure#config-location to learn how to find advanced.config file location Application code# relevant messaging-related parts of your code go here Kubernetes deployment file# Relevant parts of K8S deployment that demonstrate how RabbitMQ is deployed |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
@HakShak there is nothing wrong with the strategy you are exploring. You can temporarily have two bindings between entities A (an exchange) and its routing destination (a queue or another exchange), and if the destination is another exchange, it can in turn be bound to one or more existing queues. In fact, this ability to add more "routes" between A and B (or C via B, or whatever) has no downsides
The only thing I have to add is that RabbitMQ does not deduplicate your messages in any way. It simply aggregates N routes to compute the final list of destinations (queues or other exchanges). If you have N bindings between A and B, that won't create duplicates but not because RabbitMQ tries to deduplicate messages. What it "deduplicates" (treats as a set with unique values) is the list of destinations. |
Beta Was this translation helpful? Give feedback.
-
Alternate exchanges are used only when the initial routing step produces an empty set of destinations. If that's not the case, then RabbitMQ quite logically assumes that alternatives are not necessary because a regular route exists. |
Beta Was this translation helpful? Give feedback.
-
As an alternative, you can use two concurrent topologies: the original (OX) and new (NX) exchanges, where NX will be identical to OX except for the AE setting. OX and NX then will presumably route different messages to the same sets of queues and your publishers need to publish to one or the other, and can migrate over time. Whether this would be a more practical option than two sets of bindings plus E2Es, I am not in a position to tell. |
Beta Was this translation helpful? Give feedback.
Our own docs slightly correct my statements but match your observations.
It's a philosophical question whether the server should return the message as unroutable if it could not be routed using its original input and only the AE. I think both answers can be justified and as you can see, RabbitMQ does currently
basic.return
the message to the publisher.In any case, for your migration goal, having duplicate bindings or an exchange "routing layer" via E2Es (exchange-to-exchange bindings) is fine and the right approach. Then over time you will delete some bindings you no longer need.