7

Sto cercando di spostarmi da SQS a RabbitMQ per il servizio di messaggistica. Sto cercando di creare un servizio di accodamento stabile ad alta disponibilità. Per ora vado con il cluster.Come impostare la scalabilità automatica RabbitMQ Cluster AWS

implementazione corrente, ho tre macchine EC2 con RabbitMQ con il plugin di gestione installato in un AMI, e poi in modo esplicito vado a ciascuna della macchina e aggiungi

sudo rabbitmqctl join_cluster [email protected]<hostnameOfParentMachine> 

Con proprietà HA impostata a tutti e la sincronizzazione funziona. E un bilanciamento del carico su di esso con un DNS assegnato. Finora questa cosa funziona.

Attuazione prevista: creare un ambiente di clustering con scalabilità orizzontale in cui le macchine che vanno su/giù devono unirsi/rimuovere il cluster in modo dinamico. Qual è il modo migliore per raggiungere questo obiettivo? Per favore aiuto.

+0

basato su scala automatica? CloudWatch? – Gabriele

+0

Sì. Ma poi l'istanza in scala deve unirsi automaticamente al cluster. – Karthik

+1

Attenzione - Erlang in modalità cluster non è tollerante alle partizioni di rete (incluse le micro-partizioni) e potrebbe causare alcuni problemi; Avevo regolari micro-partizioni su AWS che avrebbero ridotto il mio cluster. Raccomanderei di eseguire un cluster di gestione temporanea per un po 'prima di impegnarmi per la produzione. –

risposta

11

Ho avuto una configurazione simile 2 anni fa.

Ho deciso di utilizzare amazon VPC, per impostazione predefinita il mio progetto aveva due istanze RabbitMQ sempre in esecuzione e configurate in cluster (dette master-node). Il cluster rabbitmq era dietro un internal amazon load balancer.

Ho creato un AMI con RabbitMQ e il plug-in di gestione configurato (chiamato "master-AMI"), quindi ho configurato le regole di scalabilità automatica.

se viene generato un allarme di autoscaling, viene avviato un nuovo master-AMI. Questa AMI esegue lo script seguito viene eseguito per la prima volta:

#!/usr/bin/env python 
import json 
import urllib2,base64 

if __name__ == '__main__': 
    prefix ='' 
    from subprocess import call 
    call(["rabbitmqctl", "stop_app"]) 
    call(["rabbitmqctl", "reset"]) 
    try: 
     _url = 'http://internal-myloadbalamcer-xxx.com:15672/api/nodes' 
     print prefix + 'Get json info from ..' + _url 
     request = urllib2.Request(_url) 

     base64string = base64.encodestring('%s:%s' % ('guest', 'guest')).replace('\n', '') 
     request.add_header("Authorization", "Basic %s" % base64string) 
     data = json.load(urllib2.urlopen(request)) 
     ##if the script got an error here you can assume that it's the first machine and then 
     ## exit without controll the error. Remember to add the new machine to the balancer 
     print prefix + 'request ok... finding for running node' 


     for r in data: 
      if r.get('running'): 
       print prefix + 'found running node to bind..' 
       print prefix + 'node name: '+ r.get('name') +'- running:' + str(r.get('running')) 
       from subprocess import call 
       call(["rabbitmqctl", "join_cluster",r.get('name')]) 
       break; 
     pass 
    except Exception, e: 
     print prefix + 'error during add node' 
    finally: 
     from subprocess import call 
     call(["rabbitmqctl", "start_app"]) 


    pass 

Gli script utilizza l'API HTTP “http://internal-myloadbalamcer-xxx.com:15672/api/nodes” per trovare i nodi, quindi scegliere una e lega il nuovo AMI al cluster.

Come politica HA ho deciso di usare questo:

rabbitmqctl set_policy ha-two "^two\."^
    "{""ha-mode"":""exactly"",""ha-params"":2,"ha-sync-mode":"automatic"}" 

Ebbene, il join è “abbastanza” facile, il problema è decidere quando è possibile rimuovere il nodo dal cluster.

Non è possibile rimuovere un nodo in base alla regola di scalabilità automatica, poiché è possibile avere messaggi sulle code che si devono consumare.

ho deciso di eseguire uno script periodicamente in esecuzione per le due istanze master-nodo che:

  • controlli i messaggi contano tramite l'API http://node:15672/api/queues
  • se i messaggi contano per tutti coda è pari a zero, posso rimuovere l'istanza dal servizio di bilanciamento del carico e quindi dal cluster rabbitmq.

Questo è ampiamente quello che ho fatto, spero che sia d'aiuto.

[EDIT]

Ho modificato la risposta, poiché non v'è questo plugin che può aiutare:

suggerisco di vedere questo: https://github.com/rabbitmq/rabbitmq-autocluster

Il plugin è stato spostato al funzionario Repository RabbitMQ, e può facilmente risolvere questo tipo di problemi

+0

La tua sceneggiatura funziona come un incantesimo! grazie mille Per quanto riguarda l'assunzione del nodo da parte del sistema di bilanciamento del carico im utilizzando la politica di scalabilità automatica in base all'utilizzo della memoria, vale a dire <40%. – Karthik

+0

Sono riuscito a farlo tramite la metrica personalizzata per la memoria come da documentazione di aws sulla metrica personalizzata. Grazie per il codice. – Karthik

+3

Il punto del cluster non è tale che è possibile rimuovere un nodo perché i dati vengono replicati tra i nodi? – Volte

0

Recentemente abbiamo avuto un problema simile.

Abbiamo provato a utilizzare https://github.com/rabbitmq/rabbitmq-autocluster ma l'abbiamo trovato complicato per il nostro caso d'uso.

Ho creato la configurazione terraform per far girare X nodi RabbitMQ su sottoreti Y (zone di disponibilità) utilizzando il Gruppo di scalabilità automatica.

TL; DR https://github.com/ulamlabs/rabbitmq-aws-cluster

La configurazione crea ruolo IAM per consentire nodi per l'individuazione automatica di tutti gli altri nodi del Gruppo Autoscaling.