Tags: rabbitmq, messaging, amqp, queues, exchanges, broker
Level: intermediate
TL;DR: RabbitMQ is a reliable message broker implementing the AMQP protocol, using exchanges to route messages from producers to queues for asynchronous decoupling.
Producer: Application that sends messages to the broker.
Consumer: Application that receives and processes messages from a queue.
Queue: FIFO buffer that stores messages until consumed.
Exchange: Routing agent that receives messages and pushes them to queues based on rules.
Binding: The link between an exchange and a queue, often using a routing key.
Direct Exchange: Routes messages to queues with an exactly matching routing key.
Topic Exchange: Routes messages using wildcard routing keys (* for exactly one word, # for zero or more).
Fanout Exchange: Broadcasts messages to all bound queues, ignoring the routing key.
Acknowledgements (ACK): Consumer informs the broker a message is processed and can be deleted.
Dead Letter Exchange (DLX): Catches messages that are rejected, expired (TTL), or dropped due to queue length limits.
Q: How do you guarantee message delivery in RabbitMQ?R: I use publisher confirms on the sender side, ensure both queues and messages are marked as durable/persistent, and require manual consumer acknowledgements.
Q: What is the difference between a connection and a channel?R: A connection is the physical TCP connection to the broker. A channel is a virtual connection inside it; I always multiplex channels to save resources instead of opening multiple connections.
Q: How do you handle failed message processing?R: I manually NACK the message without requeuing, routing it to a Dead Letter Exchange for later inspection or delayed retry.
Forgetting to acknowledge messages, causing them to stay unacked and eventually exhausting broker memory.
Opening a new TCP connection per request instead of reusing a long-lived connection and opening new channels.
Making messages persistent without making the target queue durable, meaning messages are lost if the broker restarts.
Using a fanout exchange when targeted routing is needed, leading to unnecessary load on consumers.
```import amqp from 'amqplib';
// Producer Example
async function publishMessage() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
const exchange = 'logs_topic';
const routingKey = 'error.auth';
const msg = Buffer.from('Authentication failed');
await channel.assertExchange(exchange, 'topic', { durable: true });
channel.publish(exchange, routingKey, msg, { persistent: true });
setTimeout(() => connection.close(), 500);
}
// Consumer Example
async function consumeMessages() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
const queue = 'auth_errors_queue';
await channel.assertQueue(queue, { durable: true });
await channel.bindQueue(queue, 'logs_topic', 'error.*');
channel.consume(queue, (msg) => {
if (msg !== null) {
console.log('Received:', msg.content.toString());
channel.ack(msg); // Manual acknowledgement
}
});
}
```