| Feature | ActiveMQ | RabbitMQ | Kafka |
|---|---|---|---|
| Architecture | JMS-based, supports multiple protocols | AMQP-based, optimized for AMQP | Distributed log-based system |
| Performance | Moderate throughput | High throughput | Extremely high throughput |
| Use Case | Legacy enterprise systems, JMS-based applications | Cloud-native apps, microservices, real-time messaging | Event streaming, real-time analytics, log aggregation |
| Protocol Support | Supports JMS, AMQP, MQTT, STOMP, etc. | Primarily AMQP, with plugins for others | Custom protocol, optimized for streaming |
| Ease of Use | More complex setup | Easier to set up and configure | Requires more setup and expertise |
| Scalability | Moderate scalability | High scalability with clustering | Horizontally scalable, designed for distributed systems |
| Message Ordering | Supports message ordering | Supports message ordering | Strong ordering guarantees |
| Durability | Persistent messages supported | Persistent messages supported | Highly durable with replication |
| Plugins and Extensibility | Limited plugin ecosystem | Rich plugin ecosystem | Limited plugins, but highly extensible |
| Community and Ecosystem | Smaller community, fewer integrations | Larger community, extensive integrations | Large community, strong ecosystem |
| Best For | Traditional enterprise systems | Modern cloud-native applications | Event-driven architectures, big data |
RabbitMQ is not popular anymore, we usually choose Kafka for large systems or choose a queue within cloud we use like Google pub/sub if you’re using GCP (Google Cloud Platform) or Amazon Simple Queue Service (SQS).
Today we will learn about rabbitMQ to know basis about how a queue works
direct, topic, fanout, or headers exchanges depending on routing needs.queues based on exchange type.queues and processes messages.<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>docker-compose.yml
services:
rabbitmq:
image: rabbitmq:3.12-management # Includes the web management UI
container_name: rabbitmq
restart: always
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: admin
ports:
- "5672:5672" # AMQP protocol port
- "15672:15672" # Management UI port
volumes:
- rabbitmq_data:/var/lib/rabbitmq # Persist RabbitMQ data
volumes:
rabbitmq_data:
driver: localdocker-compose up -dIn order to access web, using port 15672, http://localhost:15672
RabbitMQ supports four main types of exchanges: Direct, Fanout, Topic, and Headers.
| Exchange Type | When to Use |
|---|---|
| Direct | Specific routing based on exact keys. |
| Fanout | Broadcast to multiple consumers. |
| Topic | Pattern-based routing (e.g., logs, multi-level keys). |
| Headers | Advanced routing with custom attributes. |
Routes messages to queues with an exact matching routing key
direct exchange: direct_exchangedirect_exchange, add binding to error_queue with routing key: errordirect_exchangeerror_queue queue

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
public static final String QUEUE_NAME = "error_queue";
public static final String EXCHANGE_NAME = "direct_exchange";
public static final String ROUTING_KEY = "error";
}import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMessage(String message) {
rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME, RabbitMQConfig.ROUTING_KEY, message);
}
}
Broadcasts messages to all bound queues, ignoring routing keys.
log_queue_1, log_queue_2fanout exchange: log_exchangelog_exchange, add binding to log_queue_1, log_queue_2log_exchangelog_queue_1 and log_queue_2 queues
rabbitTemplate.convertAndSend("log_exchange", "", message);
Routes messages based on pattern matching in routing keys using:
* → Matches one word.# → Matches multiple words.Create 2 queues: app1_logs, app2_log
Create topic exchange: logs_topic
In logs_topic, create 2 binding to 2 queues
app1_loglogs.error.app1app2_loglogs.info.app2Send message to logs_topic with routing key: logs.*.app1
Only app1_log queue receive message.
Uses message headers (instead of routing keys) for routing.
pdf_logslogs_headers
logs_headers with headers: {format: "pdf", type: "report" }
public void sendHeadersMessage() {
MessageProperties messageProperties = new MessageProperties();
messageProperties.setHeader("format", "pdf");
messageProperties.setHeader("type", "report");
Message msg = new Message("Here is a headers message".getBytes(StandardCharsets.UTF_8), messageProperties);
rabbitTemplate.send("logs_headers", "", msg); // Headers exchange ignores routing keys
}