Vai al contenuto

RabbitMQ

RabbitMQ è uno dei message broker più utilizzati nel mondo backend moderno. Viene impiegato per costruire sistemi asincroni, scalabili e resilienti, ed è particolarmente adatto sia a monoliti evoluti sia ad architetture a microservizi.

In questo articolo vedremo:

  • cos’è RabbitMQ e quando usarlo;
  • i concetti fondamentali (exchange, queue, binding, routing key);
  • come installarlo (locale e Docker);
  • come gestirlo e monitorarlo;
  • come integrarlo correttamente con Symfony Messenger;
  • un progetto completo di esempio con Docker e file reali.

Cos’è RabbitMQ

RabbitMQ è un message broker open source che implementa il protocollo AMQP (Advanced Message Queuing Protocol). Il suo compito è ricevere messaggi dai produttori (producer), conservarli in modo affidabile e consegnarli ai consumatori (consumer).

A differenza di una chiamata HTTP sincrona, un messaggio in RabbitMQ viene elaborato in modo asincrono. Questo permette di:

  • ridurre il tempo di risposta delle API;
  • disaccoppiare i componenti del sistema;
  • gestire carichi elevati;
  • rendere il sistema più resiliente agli errori.

Concetti fondamentali

Producer

È il componente che invia un messaggio a RabbitMQ. Non invia il messaggio direttamente a una coda, ma a un exchange.

Exchange

L’exchange riceve il messaggio e decide come instradarlo. Esistono diversi tipi di exchange:

  • direct: instradamento basato su routing key esatta;
  • fanout: invia il messaggio a tutte le code collegate;
  • topic: instradamento basato su pattern;
  • headers: instradamento basato su header (meno usato).

Queue

La queue è dove i messaggi vengono conservati finché un consumer non li elabora. Una queue può avere più consumer.

Binding e Routing Key

Il binding collega un exchange a una queue. La routing key è una stringa che l’exchange usa per decidere se un messaggio deve essere consegnato a una determinata queue.


Installazione di RabbitMQ

Installazione su Ubuntu

RabbitMQ è scritto in Erlang, quindi è necessario installare prima Erlang.

sudo apt update
sudo apt upgrade -y
sudo apt install erlang -y
sudo apt install rabbitmq-server -y

Abilitiamo l’interfaccia di gestione:

sudo rabbitmq-plugins enable rabbitmq_management

Verifichiamo che il servizio sia attivo:

sudo systemctl status rabbitmq-server

L’interfaccia web sarà disponibile su http://localhost:15672 (utente e password di default: guest / guest).

Installazione con Docker (consigliata)

Per sviluppo e test, Docker è la soluzione migliore.

version: "3.8"

services:
  rabbitmq:
    image: rabbitmq:3.13-management
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: password
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq

volumes:
  rabbitmq_data:

Avvio:

docker compose up -d

Gestione e monitoraggio

RabbitMQ fornisce una dashboard web che consente di:

  • visualizzare exchange e queue;
  • monitorare messaggi pronti, non riconosciuti e consumati;
  • eliminare o svuotare code;
  • verificare i consumer attivi.

In produzione è consigliato affiancare:

  • metriche (Prometheus);
  • log centralizzati;
  • alert su crescita anomala delle queue.

Integrazione con Symfony Messenger

Installazione delle dipendenze

composer require symfony/messenger
composer require amqp-messenger

È necessaria anche l’estensione PHP amqp.

Configurazione ambiente

Nel file .env:

RABBITMQ_DSN=amqp://admin:password@rabbitmq:5672/%2f

Configurazione Messenger

framework:
  messenger:
    transports:
      async:
        dsn: '%env(RABBITMQ_DSN)%'
        options:
          exchange:
            name: app.exchange
            type: topic
    routing:
      'App\Message\*': async

Message e Handler

Message

<?php

namespace App\Message;

class NotificaUtente
{
    public function __construct(
        public int $idUtente,
        public string $messaggio
    ) {}
}

Handler

<?php

namespace App\MessageHandler;

use App\Message\NotificaUtente;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler]
class GestoreNotificaUtente
{
    public function __invoke(NotificaUtente $messaggio): void
    {
        // logica di elaborazione
    }
}

Dispatch

$this->bus->dispatch(
    new NotificaUtente(123, 'Benvenuto!')
);

Consumo messaggi

php bin/console messenger:consume async -vv

Progetto completo di esempio

Struttura minima:

.
├── docker-compose.yml
├── .env
├── config/
│   └── packages/
│       └── messenger.yaml
├── src/
│   ├── Message/
│   │   └── NotificaUtente.php
│   └── MessageHandler/
│       └── GestoreNotificaUtente.php

Conclusione

RabbitMQ non è solo un sistema di code, ma un componente architetturale fondamentale. Integrato correttamente con Symfony Messenger permette di costruire applicazioni robuste, scalabili e manutenibili.

La chiave è progettare fin dall’inizio naming, gestione degli errori, monitoring e struttura dei messaggi.