RabbitMQ è un broker di messaggi open source che supporta AMQP, STOMP e altre tecnologie di comunicazione. È ampiamente utilizzato nelle applicazioni aziendali e nelle moderne architetture di micro-servizi in cui funge da canale di messaggi asincrono tra diversi micro-servizi. Questa guida descriverà come è possibile raggruppare RabbitMQ su più server CentOS 7 per formare un broker di messaggi ad alta disponibilità. In questa esercitazione, un server fungerà da server principale e gli altri server fungeranno da server mirror nel caso in cui il server master non sia disponibile.
Prerequisiti
Il firewall CentOS, ( firewalld), non consente alcun traffico in entrata per impostazione predefinita. Per rendere RabbitMQ disponibile per altri sistemi all'interno e all'esterno della rete e per consentirci di accedere alla console di gestione, dobbiamo prima aprire alcune porte.
La console di gestione dell'interfaccia Web di RabbitMQ è in ascolto per impostazione predefinita sulla porta 15672. Vorremmo rendere la console di gestione disponibile al pubblico in modo da potervi accedere dal nostro computer. Pertanto forniremo istruzioni firewalldper l'apertura permanente della porta 15672nella zona pubblica (che è la zona predefinita e attiva su un'istanza Vultr).
sudo firewall-cmd --zone=public --add-port=15672/tcp --permanent
I nodi RabbitMQ devono essere in grado di comunicare tra loro. Vorremmo aprire le porte necessarie, ma solo sulla rete interna. Non vogliamo che nessuno su Internet sia in grado di amministrare o contattare direttamente i nostri server. I seguenti comandi presuppongono che i nostri server siano nella 192.168.0.100/24sottorete.
Il primo servizio è il epmdservizio di rilevamento peer che ascolta per impostazione predefinita sulla porta 4369.
sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  source address="192.168.0.100/24"
  port protocol="tcp" port="4369" accept'
Per la comunicazione internodale e CLI, RabbitMQ deve essere in grado di comunicare tramite porta 25672.
sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  source address="192.168.0.100/24"
  port protocol="tcp" port="25672" accept'
Gli strumenti della CLI comunicano nell'intervallo di porte 35672-35682.
sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  source address="192.168.0.100/24"
  port protocol="tcp" port="35672-35682" accept'
Se le tue applicazioni richiedono il protocollo AMQP, dovrai anche aprire le porte 5671e 5672. Se è necessario poter comunicare tramite un altro protocollo, è possibile trovare le informazioni necessarie sui requisiti di rete di RabbitMQ nella documentazione ufficiale di RabbitMQ .
sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  source address="192.168.0.100/24"
  port protocol="tcp" port="5672" accept'
sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  source address="192.168.0.100/24"
  port protocol="tcp" port="5671" accept'
Ora che firewalldè configurato, dobbiamo istruirlo per ricaricare la configurazione.
sudo firewall-cmd --reload
Ripetere i passaggi da questa sezione su tutti i server.
Installare rabbitmqadmin
Il plug-in di gestione viene fornito con uno strumento Python chiamato rabbitmqadminche può essere facilmente installato sul sistema una volta abilitato il plug-in di gestione.
sudo wget http://localhost:15672/cli/rabbitmqadmin
sudo mv rabbitmqadmin /usr/local/bin/
sudo chmod +x /usr/local/bin/rabbitmqadmin
È necessario utilizzare i nomi host del server per identificare i server durante il clustering. Per impostazione predefinita, i server non hanno alcun record DNS assegnato e la connessione fallirà. Per ovviare rapidamente a ciò, aggiungi il nome host master e mirror al /etc/hostsfile usando il tuo editor preferito.
Ad esempio, il file hosts del tuo master potrebbe essere simile al seguente. Notare gli ultimi due record, che consentono ai server di identificarsi a vicenda con il loro nome host. Assicurati di cambiare gli indirizzi IP con i tuoi.
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
127.0.0.1 guest
::1       guest
127.0.0.1 YOUR_MASTER_SERVER_HOST_NAME
::1       YOUR_MASTER_SERVER_HOST_NAME
192.168.0.101 YOUR_MASTER_SERVER_HOST_NAME
192.168.0.102 YOUR_MIRROR_SERVER_HOST_NAME
Cluster i nodi
Un prerequisito di importazione per consentire ai nodi di unirsi l'un l'altro è che il cookie Erlang di tutti i nodi sia identico. Per impostazione predefinita, a ciascun nodo verrà assegnato un cookie Erlang univoco, quindi è necessario riconfigurarlo su tutti i nodi.
Il seguente comando imposterà il cookie Erlang su " WE<3COOKIES", ma sentiti libero di cambiarlo a tuo piacimento. Fallo su tutti i server.
sudo sh -c "echo 'WE<3COOKIES' > /var/lib/rabbitmq/.erlang.cookie"
Riavvia RabbitMQ su tutti i server per assicurarsi che il cookie Erlang sia ricaricato correttamente.
sudo systemctl restart rabbitmq-server.service
Eseguire i comandi seguenti su tutti i server tranne sul server principale. Ciò consentirà ai nodi di unirsi al server principale e formare un cluster.
sudo rabbitmqctl stop_app
sudo rabbitmqctl join_cluster "rabbit@<YOUR_MASTER_SERVER_HOST_NAME>"
sudo rabbitmqctl start_app
Verificare che i nodi si siano uniti al cluster eseguendo il comando seguente.
sudo rabbitmqctl cluster_status
Tutti i tuoi nodi appariranno nella sezione nodese running_nodesdell'output. D'ora in poi, non sarà più necessario ripetere i passaggi su ciascun server, la configurazione verrà automaticamente rispecchiata sugli altri nodi.
Creare una politica di disponibilità elevata
Ora che abbiamo un cluster di nodi RabbitMQ, possiamo usarlo per creare code e scambi ad alta disponibilità impostando una nuova politica. Questo criterio può essere aggiunto tramite la console di gestione RabbitMQ o utilizzando l'interfaccia della riga di comando.
sudo rabbitmqctl set_policy -p "/" --priority 1 --apply-to "all" ha ".*" '{ "ha-mode": "exactly", "ha-params": 2, "ha-sync-mode": "automatic"}'
Il seguente elenco spiegherà cosa significa ogni parte del comando.
	- -p "/": Utilizzare questo criterio sul- "/"vhost (impostazione predefinita dopo l'installazione)
- --priority 1: L'ordine in cui applicare le politiche
- --apply-to "all": Può essere- "queues",- "exchanges"o- "all"
- ha: Il nome che diamo alla nostra politica
- ".*": L'espressione regolare utilizzata per decidere a quali code o scambi viene applicato questo criterio.- ".*"corrisponderà a tutto
- '{ "ha-mode": "exactly", "ha-params": 2, "ha-sync-mode": "automatic"}': La rappresentazione JSON della politica. Questo documento descrive che vogliamo: esattamente 2 nodi su cui i dati vengono sincronizzati automaticamente
In breve, questa politica assicurerà che avremo sempre 2 copie dei dati su una coda o su uno scambio, purché siano attivi e funzionanti almeno 2 nodi. Se hai più nodi puoi aumentare il valore di ha-params. Si consiglia un quorum, ( N/2 + 1), di nodi. Avere più copie dei dati comporterebbe un maggiore utilizzo di disco, I / O e rete che potrebbe comportare un peggioramento delle prestazioni.
Se si desidera eseguire il mirroring dei dati su tutti i nodi del cluster, è possibile utilizzare il seguente documento JSON.
'{ "ha-mode": "all", "ha-sync-mode": "automatic"}'
Se si desidera eseguire il mirroring dei dati solo su nodi specifici (ad esempio: node-1e node-2), è possibile utilizzare quanto segue.
'{ "ha-mode": "nodes", "ha-params" :["rabbit@node-1", "rabbit@node-2"], "ha-sync-mode": "automatic"}'
È possibile modificare l'espressione regolare per assegnare criteri diversi a code diverse. Supponiamo di avere i seguenti tre nodi:
	- coniglio @ maestro
- coniglio @ client-ha
- coniglio @ prodotto-ha
Possiamo quindi creare due criteri che comporteranno il mirroring delle rabbit@client-hacode che hanno un nome che inizia con "client" sul nodo e tutte le code che hanno un nome che inizia con "product" per il mirroring sul rabbit@product-hanodo.
sudo rabbitmqctl set_policy -p "/" --priority 1 --apply-to "queues" ha-client "client.*" '{ "ha-mode": "nodes", "ha-params": ["rabbit@master", "rabbit@client-ha"], "ha-sync-mode": "automatic"}
sudo rabbitmqctl set_policy -p "/" --priority 1 --apply-to "queues" ha-product "product.*" '{ "ha-mode": "nodes", "ha-params": ["rabbit@master", "rabbit@product-ha"], "ha-sync-mode": "automatic"}
Una piccola osservazione qui: le code esclusive non sono mai speculari o durature in RabbitMQ, anche se questa politica corrisponderebbe a tali code. Le code esclusive vengono automaticamente distrutte una volta che un client si disconnette e, come tale, non sarebbe di alcuna utilità replicarlo su un altro server. Se il server dovesse fallire, il client si disconnetterebbe da esso e la coda verrebbe automaticamente distrutta. Anche le istanze con mirroring verrebbero distrutte.
Testare l'installazione
Per testare la configurazione in cluster possiamo creare una nuova coda utilizzando l'interfaccia della riga di comando tramite la console di gestione.
sudo rabbitmqadmin declare queue --vhost "/" name=my-ha-queue durable=true
Ciò creerà una coda duratura sul /vhost predefinito con il nome my-ha-queue.
Esegui il comando seguente e verifica nell'output che alla nostra coda sia stata assegnata la nostra politica 'ha' e che i pid siano sul master e su un nodo mirror.
sudo rabbitmqctl list_queues name policy state pid slave_pids
Ora possiamo pubblicare un messaggio nella coda dal nodo principale e interrompere RabbitMQ sul nodo principale.
sudo rabbitmqadmin -u user_name -p password  publish routing_key=my-ha-queue payload="hello world"
sudo systemctl rabbitmqctl shutdown
Ora ripristinalo connettendoti al nodo mirror.
 sudo rabbitmqadmin -H MIRROR_NODE_IP_OR_DNS -u user_name -p password get queue=my-ha-queue
Finalmente, possiamo riavviare il nostro nodo principale.
sudo systemctl start rabbitmq-server.service
Elimina l'utente ospite
Come accennato in precedenza, RabbitMQ crea automaticamente un utente guest con una password guest predefinita. Sarebbe una cattiva pratica lasciare questo utente predefinito su un sistema esposto pubblicamente.
sudo rabbitmqctl delete_user guest