Nick Brady
Nick Brady

Reputation: 6592

how are messages acknowledged with multiple consumers on direct exchange

I'm trying to understand how message acknowledgement works exactly under the AMQP protocol (specifically RabbitMQ) with a direct exchange with multiple consumers subscribed to the same routing key. It is essentially a fanout exchange, but I have it so it can fan out to different consumers based on the routing_key. My current mental model looks like this: enter image description here

  1. Publisher creates "reply_to" queue and publishes to routing key with a message telling consumers to send response to queue (RPC protocol), along with a correlation id which is passed back so that all future results are tied to that unique identifier
  2. Exchange sends out message to all queues bound to that routing key. Here, there are two queues for two consumers, each bound to routing key "pumps"
  3. After some time, the consumer replies back to the reply_to queue, and then acknowledges message so that THEIR EXCLUSIVE QUEUE deletes the message that was sent to its queue. Each consumer that received a message does this.
  4. The broker sends the responses to the RPC queue. The publisher acknowledges each message it gets, acknowledging messages it receives for that

I know its confusing.. basically it comes down to this question - what is a message bound to? It is obvious in a round-robin scenario. Each message is being sent to one queue, and the consumer can ack it; however, if there are multiple consumers for the same message, it made sense to me that really, each queue (and each consumer bound to it) has its own message to the consumer, each of which must be acknowledged. Is that the case?

RabbitMQ has this to say:

https://www.rabbitmq.com/confirms.html#acknowledgement-modes Depending on the acknowledgement mode used, RabbitMQ can consider a message to be successfully delivered either immediately after it is sent out (written to a TCP socket) or when an explicit ("manual") client acknowledgement is received.

Unfortunately, this mentions nothing about queues, and what happens when there are multiple of them with their own consumers.

Upvotes: 0

Views: 1523

Answers (1)

Ansel Cadien
Ansel Cadien

Reputation: 23

With RabbitMQ, for true FanOut method, its best for each consumer to have their own queue bind to the exchange, with this each consumer will receive and consume the message without affecting other consumers

with a scenario like, Sale Rep sends orders to Cashiers, where there are multiple sale reps and multiple cashiers.

Sale rep sends order

Channel.ExchangeDeclare(exchange: "cashieradd", ExchangeType.Fanout);
                var jsonResult = JsonConvert.SerializeObject(new CashierQueue()
                {
                    transactionId = transactionId
                });
                var body = Encoding.UTF8.GetBytes(jsonResult);

                Channel.BasicPublish(exchange: "cashieradd", routingKey: "", basicProperties: null, body: body);

Each cashier would subscribe to the exchange

        {
            var cashierAddQueue = Channel.QueueDeclare().QueueName;
            Channel.QueueBind(queue: cashierAddQueue, exchange: "cashieradd", routingKey: "");
            var consumer = new EventingBasicConsumer(Channel);
            Channel.BasicConsume(queue: cashierAddQueue, autoAck: true, consumer: consumer);
            return consumer;
        }

this uses the RabbitMQ Dynamic Queue, however, any queue unique to the consumer would have the same effect.

A routingkey here is not necessarily required

Upvotes: 0

Related Questions