Reputation: 6592
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:
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.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
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