Gestione del tuo cluster RabbitMQ

RabbitMQ è un ottimo broker di messaggi distribuiti ma non è così facile da amministrare a livello di codice. In questo tutorial ti mostrerò come creare un cluster, aggiungere nodi, rimuovere nodi, avviare e fermare. Come bonus condividerò un file Fabric che ti consente di assumere il controllo totale. Il codice è disponibile su GitHub.

Introduzione rapida a RabbitMQ

RabbitMQ è una coda di messaggi molto popolare. Puoi avere più produttori che inviano messaggi e i consumatori possono consumare questi messaggi in un modo totalmente disaccoppiato. RabbitMQ è molto popolare per diversi motivi:

  1. È veloce e robusto.
  2. È open source, ma c'è un supporto commerciale se lo vuoi.
  3. Funziona sul tuo sistema operativo.
  4. È attivamente sviluppato.
  5. È stato testato in battaglia.

RabbitMQ è implementato in Erlang, che è un po 'insolito, ma uno dei motivi è così affidabile.

Prerequisiti

Ai fini di questo tutorial userò un cluster Vagrant locale di tre nodi. Se hai già tre macchine disponibili (virtuali o meno), puoi invece usarle. Presta attenzione alle porte e al networking.

Installa VirtualBox

Segui le istruzioni per installare VirtualBox.

Installa Vagrant

Segui le istruzioni per installare Vagrant

Creare un cluster RabbitMQ

Ecco un Vagrantfile che creerà un cluster locale a tre nodi sulla tua macchina. Il sistema operativo è Ubuntu 14.04 (affidabile).

ruby # - * - mode: ruby ​​- * - # vi: set ft = ruby: hosts = "rabbit-1" => "192.168.77.10", "rabbit-2" => "192.168.77.11", "rabbit -3 "=>" 192.168.77.12 " Vagrant.configure (" 2 ") do | config | config.vm.box = "trusty64" hosts.each_with_index do | (name, ip), i | rmq_port = 5672 + i admin_port = 15672 + i config.vm.define nome do | machine | machine.vm.network: private_network, ip: ip config.vm.hostname = "rabbit-% d"% [i + 1] config.vm.network: forwarded_port, guest: 5672, guest_ip: ip, host: rmq_port config. vm.network: forwarded_port, guest: 15672, guest_ip: ip, host: admin_port machine.vm.provider "virtualbox" do | v | v.name = nome fine fine fine fine

Per creare un cluster vuoto, digitare: vagabondo.

Configurazione di SSH

Per semplificare l'esecuzione di ssh nei nodi del cluster, digitare: vagrant ssh-config >> ~ / .ssh / config.

Se si digita: cat ~ / .ssh / config, dovresti vedere le voci per coniglio-1, coniglio-2 e coniglio-3.

Ora puoi ssh in ogni macchina virtuale per nome: ssh rabbit-1.

Assicurarsi che i nodi siano raggiungibili per nome

Il modo più semplice è modificare il file / etc / hosts. Ad esempio, per coniglio-1 aggiungi gli indirizzi di coniglio-2 e coniglio-3.

semplice 192.168.77.11 coniglio-2 192.168.77.12 coniglio-3

Ripeti il ​​processo per tutti i nodi.

Installa RabbitMQ

Userò apt-get qui per i sistemi operativi Debian / Ubuntu. Se il tuo cluster funziona su un sistema operativo diverso, segui le istruzioni sulla pagina di installazione di RabbitMQ.

Si noti che a volte una versione piuttosto scadente di RabbitMQ è disponibile per impostazione predefinita. Se si desidera installare il più recente e migliore, è possibile scaricare direttamente un pacchetto .deb o aggiungere il repository apt di RabbitMQ, utilizzando queste istruzioni.

La versione attuale di RabbitMQ su Ubuntu 14.04 è 3.2, che è abbastanza buona per i nostri scopi. Verifica tu stesso digitando: apt-cache mostra rabbitmq-server.

Andiamo avanti e installarlo su ogni macchina:

semplice sudo apt-get update sudo apt-get install rabbitmq-server -y

Sentiti libero di usare il tuo strumento di gestione della configurazione preferito come Chef o Ansible se preferisci.

Si noti che Erlang verrà installato prima come prerequisito.

Abilita il plugin di gestione RabbitMQ

Il plugin di gestione è davvero interessante. Offre un'API basata su HTTP, una GUI Web e uno strumento da riga di comando per gestire il cluster. Ecco come abilitarlo:

semplici sudo rabbitmq-plugins abilita rabbitmq_management

Ottieni lo strumento da riga di comando della gestione

Scaricalo da http://192.168.77.10:15672/cli/rabbitmqadmin. Si noti che la documentazione di RabbitMQ non è corretta e ti dice di scaricare da http: //: 15672 / cli /.

Questo è un client HTTP basato su Python per l'API HTTP di gestione RabbitMQ. È molto conveniente per lo scripting di cluster RabbitMQ.

Concetti base su RabbitMQ

RabbitMQ implementa lo standard AMQP 0.9.1 (Advanced Message Queue Protocol). Si noti che esiste già uno standard AMQP 1.0 e RabbitMQ ha un plugin per supportarlo, ma è considerato un prototipo a causa di un uso insufficiente del mondo reale.

Nel modello AMQP, i publisher inviano messaggi a un broker di messaggi (RabbitMQ è il broker di messaggi in questo caso) tramite uno scambio. Il broker dei messaggi distribuisce i messaggi alle code in base ai metadati associati al messaggio. I consumatori consumano messaggi dalle code. I messaggi possono o non possono essere riconosciuti. RabbitMQ supporta una varietà di modelli di programmazione su questi concetti come code di lavoro, publish-subscribe e RPC.

Gestire il tuo cluster

Esistono tre script utilizzati per gestire il cluster. Lo script rabbitmq-server avvia un server RabbitMQ (avvialo). Il comando rabbitmqctl viene utilizzato per controllare il cluster (arrestare, reimpostare, raggruppare i nodi insieme e ottenere lo stato). Il comando rabbitmqadmin, scaricato in precedenza, viene utilizzato per configurare e amministrare il cluster (dichiarare vhosts, utenti, scambi e code). La creazione di un cluster coinvolge solo rabbitmq-server e rabbitmqctl.

Innanzitutto, iniziamo il server rabbitmq come servizio (demone) su ciascuno dei nostri host rabbit-1, rabbit-2 e rabbit-3.

semplice servizio sudo rabbitmq-server start

Ciò avvierà sia l'Erlang VM che l'applicazione RabbitMQ se il nodo è inattivo. Per verificare che funzioni correttamente, digita:

plain sudo rabbitmqctl cluster_status

L'output dovrebbe essere (per rabbit-1):

stato di Cluster semplice del nodo 'rabbit @ rabbit-1' ... [nodes, [disc, ['rabbit @ rabbit-1']], running_nodes, ['rabbit @ rabbit-1'], partitions ,[]]… fatto.

Ciò significa che il nodo non è ancora in cluster con nessun altro nodo ed è un nodo disco. È anche in esecuzione come puoi vedere che appare nell'elenco dei nodi in esecuzione.

Per fermare il server, emettere il seguente comando:

plain sudo rabbitmqctl stop_app

Quindi se si controlla lo stato del cluster:

plain sudo rabbitmqctl cluster_status

L'output dovrebbe essere:

semplice stato di Cluster del nodo 'rabbit @ rabbit-1' ... [nodes, [disc, ['rabbit @ rabbit-1']]] done.

Niente più nodi in esecuzione.

Puoi ripetere il processo per gli altri nodi (coniglio-2 e coniglio-3) e vedere che sanno solo loro stessi.

Il cookie di Erlang

Prima di poter creare un cluster, tutti i nodi nel cluster devono avere lo stesso cookie. Il cookie è un file utilizzato dal runtime Erlang per identificare i nodi. Si trova in /var/lib/rabbitmq/.erlang.cookie. Basta copiare il contenuto da coniglio-1 a coniglio-2 e coniglio-3.

Raggruppamento di nodi insieme

Raggruppare questi nodi separati in un cluster coeso richiede un po 'di lavoro. Ecco la procedura:

  • Avere un singolo nodo in esecuzione (ad es. Coniglio-1).
  • Fermare un altro nodo (ad es. Coniglio-2).
  • Reimposta il nodo interrotto (rabbit-2).
  • Raggruppa l'altro nodo sul nodo radice.
  • Avvia il nodo interrotto.

Facciamolo. ssh in rabbit-2 ed esegui i seguenti comandi:

plain sudo rabbitmqctl stop_app sudo rabbitmqctl reset sudo rabbitmqctl join_cluster rabbit @ rabbit-1

Adesso scrivi: sudo rabbitmqctl cluster_status.

L'output dovrebbe essere:

"stato di Cluster semplice del nodo 'rabbit @ rabbit-2' ... [nodes, [disc, ['rabbit @ rabbit-1', 'rabbit @ rabbit-2']]] ... Fatto. Come puoi vedere entrambi i nodi sono ora raggruppati in cluster. Se lo ripeti su rabbit-1 otterrai l'output seguente:

Stato del cluster del nodo "rabbit @ rabbit-1" ... [nodes, [disc, ['rabbit @ rabbit-1', 'rabbit @ rabbit-2']], running_nodes, ['rabbit @ rabbit- 1 '], partitions, []] ... done. "

Ora puoi iniziare con rabbit-2.

plain sudo rabbitmqctl start_app

Se controlli di nuovo lo stato, entrambi i nodi saranno in esecuzione:

stato di Cluster semplice del nodo 'rabbit @ rabbit-2' ... [nodes, [disc, ['rabbit @ rabbit-1', 'rabbit @ rabbit-2']], running_nodes, ['rabbit @ rabbit -1 ',' rabbit @ rabbit-2 '], partitions, []] ... fatto.

Si noti che entrambi i nodi sono nodi disco, il che significa che memorizzano i propri metadati sul disco. Aggiungiamo rabbit-3 come nodo RAM. ssh to rabbit-3 e emettere i seguenti comandi:

plain sudo rabbitmqctl stop_app sudo rabbitmqctl reset sudo rabbitmqctl join_cluster --ram rabbit @ rabbit-2 sudo rabbitmqctl start_app

Il controllo dello stato mostra:

stato di Cluster semplice del nodo 'rabbit @ rabbit-3' ... [nodes, [disc, ['rabbit @ rabbit-2', 'rabbit @ rabbit-1'], ram, ['rabbit @ rabbit-3 ']], running_nodes, [' rabbit @ rabbit-1 ',' rabbit @ rabbit-2 ',' rabbit @ rabbit-3 '], partitions, []] ... fatto.

Tutti i nodi del cluster sono in esecuzione. I nodi Disc sono rabbit-1 e rabbit-2 e il nodo RAM è rabbit-3.

Congratulazioni! Hai un cluster RabbitMQ funzionante.

Complicazioni del mondo reale

Cosa succede se si desidera modificare la configurazione del cluster? Dovrai usare la precisione chirurgica quando aggiungi e rimuovi i nodi dal cluster.

Cosa succede se un nodo non viene ancora riavviato, ma si tenta di andare avanti stop_app, reset e start_app? Bene, il comando stop_app apparentemente riuscirà, restituendo "done" anche se il nodo di destinazione è inattivo. Tuttavia, il comando di reset successivo fallirà con un messaggio sgradevole. Ho passato molto tempo a grattarmi la testa cercando di capirlo, perché pensavo che il problema fosse qualche opzione di configurazione che riguardava solo il reset.

Un altro trucco è che se si desidera ripristinare l'ultimo nodo del disco, è necessario utilizzare force_reset. Cercare di capire nel caso generale quale nodo fosse l'ultimo nodo del disco non è banale.

RabbitMQ supporta anche il clustering tramite file di configurazione. Questo è ottimo quando i nodi del disco sono attivi, poiché i nodi RAM riavviati si limiteranno a cluster in base al file di configurazione senza doverli raggruppare in modo esplicito. Di nuovo, non vola quando si tenta di recuperare un cluster rotto.

Raggruppamento affidabile di RabbitMQ

Si tratta di questo: non si sa quale sia stato l'ultimo nodo del disco a scendere. Non si conoscono i metadati di clustering di ciascun nodo (forse è andato giù durante il reset). Per avviare tutti i nodi, utilizzo il seguente algoritmo:

  • Avvia tutti i nodi (almeno l'ultimo nodo del disco dovrebbe essere in grado di avviarsi).
  • Se nemmeno un singolo nodo può iniziare, tu verrai protetto. Basta salvare.
  • Tieni traccia di tutti i nodi che non sono riusciti a iniziare.
  • Prova ad avviare tutti i nodi guasti.
  • Se alcuni nodi non sono stati avviati la seconda volta, verrai protetto. Basta salvare.

Questo algoritmo funzionerà finché l'ultimo nodo del disco sarà fisicamente OK.

Una volta che tutti i nodi del cluster sono attivi, è possibile riconfigurarli (ricordare che non si è sicuri di quali siano i metadati di clustering di ciascun nodo). La chiave è force_reset ogni nodo. Ciò garantisce che qualsiasi traccia della precedente configurazione del cluster venga cancellata da tutti i nodi. Per prima cosa fallo per un nodo del disco:

plain stop_app force_reset start_app

Quindi per ogni altro nodo (disco o RAM):

plain stop_app force_reset join_cluster [elenco dei nodi del disco] start_app

Controllo remoto di un cluster

Puoi inserire SSH in ogni casella ed eseguire manualmente i passaggi sopra indicati su ciascuna scatola. Funziona, ma invecchia molto velocemente. Inoltre, non è pratico se si desidera costruire e abbattere un cluster come parte di un test automatico.

Una soluzione è usare Fabric. Una cosa seria che ho incontrato è che quando ho eseguito manualmente l'algoritmo del cluster di build ha funzionato perfettamente, ma quando ho usato Fabric è fallito misteriosamente. Dopo un po 'di debug ho notato che i nodi sono stati avviati con successo, ma quando ho provato a stop_app, i nodi erano inattivi. Questo risultò essere un errore newbie Fabric da parte mia. Quando si invia un comando remoto utilizzando Fabric, viene avviata una nuova shell sulla macchina remota. Al termine del comando, la shell viene chiusa, inviando un SIGHUP (Hang up signal) a tutti i suoi sub-processi, incluso il nodo Erlang. Usando nohup ci si prende cura di questo. Un'altra opzione più efficace è eseguire RabbitMQ come servizio (daemon).

Amministrazione di un cluster a livello di codice

Amministrazione significa creare host virtuali, utenti, scambi e code, impostare permessi e code di binding per gli scambi. La prima cosa che dovresti fare se non lo hai già è installare i plugin di gestione. Non sono sicuro del motivo per cui devi abilitarlo da solo. Dovrebbe essere abilitato di default.

L'interfaccia utente web è fantastica e devi assolutamente familiarizzarti con essa. Tuttavia, per amministrare un cluster in remoto, è possibile utilizzare un'API di gestione RESTful. C'è anche uno strumento da riga di comando Python chiamato rabbitmqadmin che richiede Python 2.6+. Usare rabbitmqadmin è piuttosto semplice. L'unico problema che ho riscontrato è che potevo utilizzare solo l'account guest predefinito per amministrare il cluster. Ho creato un altro utente amministratore chiamato "admin", ho impostato le sue autorizzazioni a tutti (configure / read / write) e gli ho assegnato un tag "administrator" (requisito aggiuntivo dell'API di gestione), ma ho continuato a ricevere errori di autorizzazione.

Il progetto Elmer ti consente di specificare una configurazione del cluster come una struttura dati Python (vedi il file sample_config.py) e imposterà tutto per te.

Punti Take-Home

  1. RabbitMQ è bello.
  2. La storia dell'amministratore del cluster non è a tenuta d'aria.
  3. L'amministrazione programmatica è la chiave.
  4. Fabric è un fantastico strumento per controllare a distanza più box Unix.