Home/Learn/RabbitMQ/RabbitMQ & AMQP Introduction

RabbitMQ & AMQP Introduction

Beginner
Fundamentals

RabbitMQ 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.

Java — Spring AMQP exchange, queue, binding
// 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.

Java — publish and consume with JSON converter
// 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.

Java — durable queue, persistent messages, manual ack
// 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 Aria
1

What is the difference between an exchange and a queue in RabbitMQ?

EasyInfosys
2

What are the four exchange types in RabbitMQ and how do they route messages?

MediumAmazon
3

What is the difference between durable queues and persistent messages?

MediumWipro
4

What happens when a consumer nacks a message with requeue=false?

MediumNetflix
5

How does manual acknowledgement mode improve reliability compared to auto-ack?

MediumPivotal

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.

Loading discussion…