I message broker sono applicazioni intermediarie utilizzate in diverse architetture software, come i microservizi. Trasferiscono informazioni sotto forma di messaggi da un servizio all’altro.
Un concetto comune associato ai message broker è il modello publisher-subscriber (pubblicatore-sottoscrittore), in cui gli eventi vengono inviati dai cosiddetti publisher (Produttori) ai subscriber (Consumatori).

In genere, un componente intermedio — un message broker — partecipa all’implementazione di questo modello.

Per semplificare, usiamo un’analogia. Pensa a YouTube: ci sono canali a cui puoi iscriverti per ricevere notifiche. Quando viene pubblicato un nuovo video (un evento), ricevi una notifica perché sei iscritto.

Tre termini principali sono importanti qui: Exchange, Queue e Binding.

Altri termini importanti:
Ecco una spiegazione passo passo di come funziona il processo:





RabbitMQ è un popolare message broker open source basato sul protocollo AMQP (Advanced Message Queuing Protocol), un protocollo aperto per la trasmissione di messaggi di eventi tramite un broker dedicato. AMQP offre un’ampia gamma di funzionalità e, oltre a RabbitMQ, è implementato anche da altri sistemi come Apache Qpid.
RabbitMQ è scritto nel linguaggio di programmazione Erlang, e i suoi principali vantaggi sono l’elevata velocità di trasmissione e la massima flessibilità di instradamento. RabbitMQ offre numerose opzioni di configurazione per definire le regole su quali messaggi vengono inviati e dove vengono elaborati.
Le connessioni a RabbitMQ avvengono tramite il protocollo TCP: il client avvia una connessione con l’indirizzo host e la mantiene aperta per tutto il tempo necessario all’interazione con RabbitMQ. RabbitMQ supporta anche l’autenticazione, come login e password, per garantire un accesso sicuro.
RabbitMQ è composto dal server e dalla WebUI (interfaccia di amministrazione). La WebUI consente di monitorare ciò che accade all’interno del broker, ad esempio verificare se i nodi del cluster sono attivi, vedere quanti messaggi sono in elaborazione e altro ancora. Vediamo come installare RabbitMQ su diversi sistemi operativi.
Prima di iniziare, dobbiamo aggiornare il nome host del server. Esegui il seguente comando:
sudo hostnamectl set-hostname <nuovo-hostname>
Ad esempio, useremo rabbitmq come hostname per questo server:
sudo hostnamectl set-hostname rabbitmq
Installa nano:
sudo apt install nano
E modifica il file /etc/hosts per includere il nuovo hostname:
sudo nano /etc/hosts
Deve apparire così:
127.0.0.1 <nuovo-hostname>
Nel nostro esempio:
127.0.0.1 rabbitmq
Installeremo RabbitMQ su Ubuntu 22.04. Per altre distribuzioni Ubuntu/Debian, consulta la guida sul sito ufficiale.
Aggiorna la lista dei pacchetti e installa le dipendenze:
sudo apt-get update -y
sudo apt-get install curl gnupg -y
sudo apt-get install apt-transport-https
Aggiungi le chiavi di firma del repository:
curl -1sLf "https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA" | sudo gpg --dearmor | sudo tee /usr/share/keyrings/com.rabbitmq.team.gpg > /dev/null
curl -1sLf https://github.com/rabbitmq/signing-keys/releases/download/3.0/cloudsmith.rabbitmq-erlang.E495BB49CC4BBE5B.key | sudo gpg --dearmor | sudo tee /usr/share/keyrings/rabbitmq.E495BB49CC4BBE5B.gpg > /dev/null
curl -1sLf https://github.com/rabbitmq/signing-keys/releases/download/3.0/cloudsmith.rabbitmq-server.9F4587F226208342.key | sudo gpg --dearmor | sudo tee /usr/share/keyrings/rabbitmq.9F4587F226208342.gpg > /dev/null
Crea il file del repository (Apt Source List):
sudo tee /etc/apt/sources.list.d/rabbitmq.list <<EOF
deb [arch=amd64 signed-by=/usr/share/keyrings/rabbitmq.E495BB49CC4BBE5B.gpg] https://ppa1.rabbitmq.com/rabbitmq/rabbitmq-erlang/deb/ubuntu jammy main
deb-src [signed-by=/usr/share/keyrings/rabbitmq.E495BB49CC4BBE5B.gpg] https://ppa1.rabbitmq.com/rabbitmq/rabbitmq-erlang/deb/ubuntu jammy main
deb [arch=amd64 signed-by=/usr/share/keyrings/rabbitmq.E495BB49CC4BBE5B.gpg] https://ppa2.rabbitmq.com/rabbitmq/rabbitmq-erlang/deb/ubuntu jammy main
deb-src [signed-by=/usr/share/keyrings/rabbitmq.E495BB49CC4BBE5B.gpg] https://ppa2.rabbitmq.com/rabbitmq/rabbitmq-erlang/deb/ubuntu jammy main
deb [arch=amd64 signed-by=/usr/share/keyrings/rabbitmq.9F4587F226208342.gpg] https://ppa1.rabbitmq.com/rabbitmq/rabbitmq-server/deb/ubuntu jammy main
deb-src [signed-by=/usr/share/keyrings/rabbitmq.9F4587F226208342.gpg] https://ppa1.rabbitmq.com/rabbitmq/rabbitmq-server/deb/ubuntu jammy main
deb [arch=amd64 signed-by=/usr/share/keyrings/rabbitmq.9F4587F226208342.gpg] https://ppa2.rabbitmq.com/rabbitmq/rabbitmq-server/deb/ubuntu jammy main
deb-src [signed-by=/usr/share/keyrings/rabbitmq.9F4587F226208342.gpg] https://ppa2.rabbitmq.com/rabbitmq/rabbitmq-server/deb/ubuntu jammy main
EOF
Aggiorna nuovamente la lista dei pacchetti:
sudo apt-get update -y
Installa Erlang:
sudo apt-get install -y erlang-base \
erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \
erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \
erlang-runtime-tools erlang-snmp erlang-ssl \
erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl
Infine, installa RabbitMQ:
sudo apt-get install rabbitmq-server -y --fix-missing
Una volta completata l’installazione, verifica che il server RabbitMQ sia in esecuzione:
systemctl status rabbitmq-server
Crea un utente personalizzato:
sudo rabbitmqctl add_user <tuo-username> <tua-password>
Assegna le autorizzazioni necessarie:
sudo rabbitmqctl set_user_tags <tuo-username> administrator
sudo rabbitmqctl set_permissions -p / <tuo-username> ".*" ".*" ".*"
Poi abilita la console di gestione RabbitMQ:
sudo rabbitmq-plugins enable rabbitmq_management
Accedi a [il tuo IP del server]:15672. Inserisci il tuo nome utente e la tua password per entrare nella WebUI di RabbitMQ.

La guida di installazione è disponibile sul sito Web di RabbitMQ. Puoi utilizzare Chocolatey o il classico programma di installazione.
Prima di installare RabbitMQ, è necessario installare Erlang/OTP dal sito ufficiale di Erlang.

Esegui il file scaricato e segui il processo di installazione.
Dopo aver installato Erlang, puoi installare RabbitMQ utilizzando l’installer ufficiale.
Abilita poi la WebUI:
cd 'C:\Program Files\RabbitMQ Server\rabbitmq_server-3.13.0\sbin'
./rabbitmq-plugins.bat enable rabbitmq_management
Ora puoi accedere a localhost:15672 utilizzando il nome utente e la password predefiniti guest:guest.
L’installazione tramite Docker è probabilmente il modo più semplice e comodo per configurare RabbitMQ.
Puoi installare RabbitMQ con il seguente comando:
docker run --rm -p 15672:15672 rabbitmq:3.13.7-management
L’interfaccia di amministrazione sarà disponibile sulla porta 15672, dove potrai accedere con le credenziali predefinite guest:guest.
Tuttavia, questo metodo non è adatto a un ambiente di produzione. Docker assegna un nome al container e il broker memorizza il suo stato in una cartella con quel nome. Ad ogni nuova build del container, RabbitMQ perderà le informazioni sullo stato.
Possiamo definire comodamente tutti i parametri di servizio necessari con docker-compose, come modificare le credenziali di accesso predefinite o montare una cartella per la persistenza dello stato. Ecco un esempio di file docker-compose.yml:
version: "3.3"
services:
rabbit:
image: rabbitmq:3.13.7-management
environment:
- RABBITMQ_DEFAULT_USER=admin #enter your username
- RABBITMQ_DEFAULT_PASS=password #enter your password
volumes:
- ./rabbit:/var/lib/rabbitmq # mounting folder for state persistence
ports:
- 15672:15672 # expose port for the admin interface
Esegui:
docker compose up -d
La WebUI di RabbitMQ sarà ora disponibile.
Nella pagina principale dell’interfaccia di gestione di RabbitMQ puoi visualizzare informazioni generali come i nodi, il loro stato, il numero totale di messaggi e altro.



Esaminiamo più da vicino gli Exchanges.

Esistono diversi tipi di Exchanges, ognuno con il proprio meccanismo di filtraggio dei messaggi. In base a queste regole, gli eventi vengono instradati verso code specifiche.
Direct Exchange
Ogni messaggio ha una chiave chiamata Routing Key. I messaggi vengono inviati alle code il cui binding specifica la stessa chiave.

Topic Exchange
L’instradamento avviene in base a un modello di chiave. Quando si crea il modello, è possibile utilizzare 0 o più parole (lettere e numeri) separate da punti, ad esempio key.event, e i simboli # e *.

Fanout Exchange
Non vengono applicate regole di filtro. Ogni messaggio inviato a un Fanout Exchange viene instradato a tutte le code.

Headers Exchange
Utilizza gli header dei messaggi confrontando le coppie chiave-valore con gli header di binding.

Visualizzando una coda specifica, puoi vedere un grafico che mostra quanti messaggi sono presenti, insieme a statistiche sui tempi di consegna e di ricezione.

I messaggi possono avere due stati:
Vediamo come utilizzare RabbitMQ per implementare il modello Pub-Sub in Python. Devi avere Python installato (in questo esempio, la versione 3.11.5) e la libreria Pika.
Crea o seleziona una cartella in cui risiederà il codice dell’applicazione:
mkdir rabbitmq-article
Apri questa cartella nel tuo IDE (ad esempio Visual Studio Code o PyCharm).
Installa la libreria Pika:
pip install pika
Crea due file: sender.py e receiver.py.
from pika import BlockingConnection, ConnectionParameters
from pika.exchange_type import ExchangeType
# Create connection, specifying parameters in the ConnectionParameters object
connection = BlockingConnection(ConnectionParameters(host='localhost'))
# Create a channel
channel = connection.channel()
# Declare an exchange
channel.exchange_declare('new_exchange', ExchangeType.direct)
# Declare a queue
queue = channel.queue_declare(queue='new_queue')
# Bind the queue to the exchange
channel.queue_bind(exchange='new_exchange', queue='new_queue', routing_key='key')
# Publish a message
channel.basic_publish(exchange='new_exchange', routing_key='key', body='Hello World!')
print("Message 'Hello World!' sent")
connection.close()
Nel codice sopra di sender.py:
Si stabilisce una connessione a RabbitMQ su localhost.
Si dichiara un exchange diretto chiamato new_exchange.
Si dichiara una coda chiamata new_queue.
Si collega la coda all’exchange utilizzando la chiave di routing key.
Infine, si pubblica il messaggio 'Hello World!' sull’exchange con la chiave di routing specificata.
from pika import BlockingConnection, ConnectionParameters
from pika.exchange_type import ExchangeType
import sys, os
def main():
# Create connection
connection = BlockingConnection(ConnectionParameters(host='localhost'))
# Create channel
channel = connection.channel()
# Declare an exchange
channel.exchange_declare('new_exchange', ExchangeType.direct)
# Declare a queue
queue = channel.queue_declare(queue='new_queue')
# Bind the queue to the exchange
channel.queue_bind(exchange='new_exchange', queue='new_queue', routing_key='key')
# Function to handle incoming messages
def handle(ch, method, properties, body):
print(f"Received message: {body.decode()}")
# Bind the callback function and queue
channel.basic_consume(queue='new_queue', on_message_callback=handle, auto_ack=True)
print('Waiting for messages. Press Ctrl+C to exit.')
channel.start_consuming()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
try:
sys.exit(0)
except SystemExit:
os._exit(0)
Nel codice sopra di receiver.py:
Si stabilisce una connessione e un canale a RabbitMQ, come nel sender.
Si dichiara l’exchange diretto (new_exchange) e la coda (new_queue).
La coda è collegata all’exchange tramite la chiave di routing key.
La funzione handle() elabora i messaggi stampandoli alla ricezione.
Il metodo basic_consume() sottoscrive la funzione di callback alla coda.
Si utilizza start_consuming() per mantenere il processo in attesa di messaggi indefinitamente.
Avvia prima il receiver:
python receiver.py
Dovresti vedere:
Waiting for messages. Press Ctrl+C to exit.
Poi esegui il sender:
python sender.py
Output:
Message 'Hello World!' sent
Nel terminale dove viene eseguito il receiver, vedrai:
Received message: Hello World!
Nella console di gestione di RabbitMQ potrai vedere che l’exchange new_exchange è collegato alla coda new_queue tramite la chiave di routing key.
In questo articolo abbiamo esplorato cosa sono i message broker, come le applicazioni interagiscono con essi e come installare e utilizzare RabbitMQ come message broker. Abbiamo implementato con successo un modello publisher-subscriber utilizzando Python, RabbitMQ e la libreria Pika, in cui il mittente pubblica messaggi su un exchange e il ricevitore li consuma.