-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A new local random exchange #8334
Conversation
6d4b648
to
972c295
Compare
b33aa2a
to
cd5de9b
Compare
I am wondering about the current behaviour with this exchange. Currently if there are more than one locally bound queue it will select a random one and if there are no locally bound queues it will select a random one from the full set of queues. So in the latter case it is no longer "local". The alternative behaviour would be that it will deliver to all locally bound queues and never to queues that are not locally bound. Looking for thoughts on this. |
If there are no locally bound queues, I would expect the message to be treated like an unroutable message. My reasoning is that avoiding inter-node traffic contributes to maintaining the low latency sold by this exchange. And there is "local" in the name, not "maybe_local". Or, there could be an argument to configure the behavior. If there are many locally bound queues, I'm not sure. Perhaps the routing queue should be taken into account? Unrelated to @kjnilsson questions, is there any value in providing this exchange as a plugin, as opposed to inside the broker? |
@dumbbell we had a chat in slack about this and it seems the consensus is it should be strictly local and if a fallback is needed then an alternative exchange should be configured. |
Probably not but all non-standard exchange types are AFAIK plugins so it is just following suite. |
Ah ok, I didn't follow the discussion there, but apparently we reached the same conclusion :-) I updated my message above to give my reasoning about this.
That's what I thought but maybe it's a good time to revisit this decision. I see no value in the plugin format here. However, I see plenty of issues:
We are not saving any resources by putting that in a plugin. |
I'm up for this |
filter_local_queue(Q) -> | ||
{ok, Queue} = rabbit_amqqueue:lookup(Q), | ||
Qpid = amqqueue:get_pid(Queue), | ||
erlang:node(Qpid) =:= node(). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will throw a badarg
for quorum queues, as it is not an Erlang pid.
which preferrebly sends messages to the local bound queue
cd5de9b
to
c5d85ac
Compare
Should we make this NOT a plugin then, and if so where should be the module? In |
I think the TODO list of this PR is:
|
Replaced by #10091 |
Proposed Changes
This is a new exchange type which works like the random exchange but only selects from bound queues that are on the same local node as the publishing connection.
In scenarios where at least one queue per RabbitMQ node is bound this exchange provides high publishing availability with no additional network hops which also reduces publishing latency.
Use case scenario
In a RabbitMQ cluster of three nodes: A, B and C.
3 classic (v2) queues are declared, one on each node: q-A, q-B and q-C and they are all bound to the same instance of the
rabbitmq_local_exchange
type.A message published to the exchange on node A will only be delivered to queue: a-A, a message published on node B will only be delivered to q-B and so on. This is enough to provide very high publishing availability at very low latency.
Consumers
The consuming side is somewhat more complex. Users need to ensure that there are consuming applications to cover all queues and that at least one consumer is connected to each node. This means there need to be at least one consuming connection per RabbitMQ node. In this instance we need at least 3 consuming applications: c-A, c-B and c-C each connected to their own RabbitMQ node and consuming from the queue declared on each node: c-A is connected to node A and consumes from q-A etc.
To provide more consumption availability each consumer could connect to all nodes and consume from all queues. If competing consumption isn't desired then the queues could use the single active consumer feature.
This pattern does push quite a bit of topological knowledge onto the consuming applications, for example they need to know which queues are running on which nodes so that they can ensure we don't accidentally introduce and additional network hop for consumer delivery. But once this is set up very low latency consumption at high availability is possible.
Types of Changes
What types of changes does your code introduce to this project?
Put an
x
in the boxes that applyTODO