RabbitMQ & AMQP Introduction
BeginnerRabbitMQ is an open-source message broker implementing AMQP 0-9-1; producers publish messages to exchanges, which route them to queues consumed by subscribers.
Overview
RabbitMQ is an open-source message broker written in Erlang, implementing the AMQP 0-9-1 protocol. The core model: producers publish messages to exchanges; exchanges route messages to queues via bindings; consumers subscribe to queues and process messages. RabbitMQ supports four exchange types (direct, fanout, topic, headers), persistent messaging, acknowledgements, dead-letter queues, and a management UI. It excels at task queues, complex routing, low-latency messaging, and scenarios requiring per-message TTL, priority, or RPC patterns.
Core AMQP Model
The AMQP model separates message routing (exchanges) from message storage (queues). Producers never publish directly to queues — they publish to exchanges with a routing key. The exchange applies its routing algorithm to forward the message to bound queues.
// AMQP model overview:
//
// Producer
// │ publish(exchange="orders", routingKey="order.placed", body)
// ▼
// Exchange (orders) ← routing rules
// │ binding key="order.placed" → Queue: "order-processor"
// │ binding key="order.*" → Queue: "order-audit-log"
// ▼
// Queue (order-processor)
// │ deliver
// ▼
// Consumer (inventory-service)
// Spring Boot connection
// application.properties
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=secret
spring.rabbitmq.virtual-host=/
// Declare exchange, queue, and binding with Spring AMQP
@Configuration
public class RabbitConfig {
@Bean public TopicExchange ordersExchange() {
return new TopicExchange("orders");
}
@Bean public Queue orderProcessorQueue() {
return QueueBuilder.durable("order-processor").build();
}
@Bean public Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("order.placed");
}
}Publish & Consume Messages
RabbitTemplate sends messages; @RabbitListener receives them. Spring's message converter (Jackson2JsonMessageConverter) handles Java ↔ JSON serialisation automatically when configured.
// Configure JSON converter
@Bean
public MessageConverter jsonConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory cf,
MessageConverter converter) {
RabbitTemplate template = new RabbitTemplate(cf);
template.setMessageConverter(converter);
return template;
}
// Producer
@Service
public class OrderEventPublisher {
private final RabbitTemplate rabbitTemplate;
public void publishOrderPlaced(OrderEvent event) {
rabbitTemplate.convertAndSend(
"orders", // exchange name
"order.placed", // routing key
event // auto-serialised to JSON
);
}
}
// Consumer
@Component
public class InventoryConsumer {
@RabbitListener(queues = "order-processor")
public void handleOrderPlaced(OrderEvent event) {
// Jackson deserialises JSON back to OrderEvent
inventoryService.reserve(event.getItems());
// auto-ack on method return; exception → nack → requeue
}
}Message Durability & Acknowledgements
For reliable messaging, mark the queue as durable, mark messages as persistent (delivery mode 2), and use manual acknowledgements so messages are only removed once successfully processed.
// Durable queue — survives broker restart
@Bean
public Queue durableQueue() {
return QueueBuilder.durable("order-processor") // durable=true
.build();
}
// Persistent message (delivery mode = 2)
rabbitTemplate.convertAndSend("orders", "order.placed", event, msg -> {
msg.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
return msg;
});
// Manual acknowledgement
// application.properties
spring.rabbitmq.listener.simple.acknowledge-mode=manual
@RabbitListener(queues = "order-processor")
public void process(OrderEvent event, Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long tag)
throws IOException {
try {
inventoryService.reserve(event.getItems());
channel.basicAck(tag, false); // ack — remove from queue
} catch (Exception e) {
channel.basicNack(tag, false, true); // nack — requeue
}
}Key Points to Remember
- 1Producers publish to exchanges, not queues — exchanges route via binding rules.
- 2Four exchange types: direct (exact match), fanout (broadcast), topic (wildcard), headers.
- 3Durable queues survive broker restart; persistent messages survive broker restart.
- 4Manual ack ensures messages are removed only after successful processing.
- 5nack with requeue=true returns the message to the front of the queue.
- 6Dead-letter exchange (DLX) captures nacked or expired messages for inspection or retry.
Interview Questions
Sign in to ask AriaWhat is the difference between an exchange and a queue in RabbitMQ?
What are the four exchange types in RabbitMQ and how do they route messages?
What is the difference between durable queues and persistent messages?
What happens when a consumer nacks a message with requeue=false?
How does manual acknowledgement mode improve reliability compared to auto-ack?
Ask Aria about RabbitMQ & AMQP Introduction
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.