RabbitMQ
🐰 Che cos’è RabbitMQ?
RabbitMQ è un broker di messaggistica open-source che permette a diverse applicazioni o microservizi di comunicare in modo asincrono tramite messaggi.
In altre parole, invece che comunicare direttamente tramite chiamate HTTP sincrone, i servizi scambiano messaggi che RabbitMQ riceve, smista e distribuisce.
🔍 Quando e perché usarlo?
Lo usi quando:
- Vuoi comunicazione asincrona tra servizi (maggiore resilienza).
- Devi scalare facilmente (se hai tanti servizi/produttori-consumatori).
- Vuoi separare nettamente i servizi, riducendo l’accoppiamento (loose coupling).
- Devi gestire code affidabili e garantire la delivery dei messaggi.
🎯 Concetti fondamentali di RabbitMQ
Questi sono i concetti chiave per iniziare:
-
Producer (publisher) Invia messaggi verso RabbitMQ.
-
Consumer (subscriber) Riceve e processa messaggi da RabbitMQ.
-
Exchange Smista i messaggi ricevuti dai producer verso una o più code, secondo delle regole chiamate “bindings”.
-
Queue (coda) Struttura che memorizza i messaggi in attesa di essere processati dai consumer.
-
Binding Regole che determinano come i messaggi passano dagli exchange alle code.
📬 Tipi principali di exchange
RabbitMQ ha 4 tipi principali di exchange:
| Tipo | Uso pratico |
|---|---|
| Direct | Routing esatto tramite routing-key |
| Topic | Routing tramite pattern |
| Fanout | Broadcast a tutte le code collegate |
| Headers | Routing tramite intestazioni del messaggio (meno comune) |
Per iniziare, Direct e Topic sono i più frequenti in ambito Java/Spring.
🚀 RabbitMQ con Java e Spring (Spring AMQP)
Spring fornisce Spring AMQP, un modulo facilissimo per gestire RabbitMQ nelle applicazioni Java.
Dipendenze Maven di base:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
Questa dipendenza include già tutto ciò che ti serve per comunicare con RabbitMQ.
📌 Configurare RabbitMQ con Spring
Ecco una configurazione minima in Spring:
@Configuration
public class RabbitConfig {
public static final String QUEUE_NAME = "taskete-queue";
public static final String EXCHANGE_NAME = "taskete-exchange";
public static final String ROUTING_KEY = "taskete.key";
@Bean
Queue queue() {
return new Queue(QUEUE_NAME, true);
}
@Bean
DirectExchange exchange() {
return new DirectExchange(EXCHANGE_NAME);
}
@Bean
Binding binding(Queue queue, DirectExchange exchange) {
return BindingBuilder.bind(queue)
.to(exchange)
.with(ROUTING_KEY);
}
}
Qui hai configurato:
- una coda (
Queue) - un exchange di tipo direct (
DirectExchange) - un binding (con routing-key) tra exchange e coda
🎈 Inviare messaggi (Producer)
Usando RabbitTemplate:
@Service
public class TasketeProducer {
private final RabbitTemplate rabbitTemplate;
public TasketeProducer(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void sendMessage(String message) {
rabbitTemplate.convertAndSend("taskete-exchange", "taskete.key", message);
}
}
📥 Ricevere messaggi (Consumer)
Semplicissimo con @RabbitListener:
@Service
public class TasketeConsumer {
@RabbitListener(queues = "taskete-queue")
public void handleMessage(String message) {
System.out.println("Ricevuto: " + message);
// Logica di business qui
}
}
📋 Buone pratiche con RabbitMQ e Java/Spring
- Gestione errori: usa Dead-Letter Queue (DLQ) per messaggi non processati.
- Logging e monitoraggio: monitora dimensioni code e rate di elaborazione messaggi.
- Resilienza: configura connessioni, retries, acknowledgements manuali (quando necessario).
- Dockerizzazione: RabbitMQ può facilmente essere containerizzato con Docker.
Esempio di Docker Compose:
rabbitmq:
image: rabbitmq:3-management
container_name: taskete-rabbitmq
ports:
- "5672:5672"
- "15672:15672" # UI di gestione
networks:
- taskete-net