Hantera din RabbitMQ Cluster

RabbitMQ är en stor distribuerad budskapsmäklare men inte så lätt att administrera programmatiskt. I denna handledning visar jag dig hur man skapar ett kluster, lägger till noder, tar bort noder, startar och stoppar. Som en bonus delar jag en Fabric-fil som låter dig ta total kontroll. Koden är tillgänglig på GitHub.

Snabb Introduktion till RabbitMQ

RabbitMQ är en mycket populär meddelandekö. Du kan få flera producenter att skicka meddelanden, och konsumenterna kan konsumera dessa meddelanden på ett helt avkopplat sätt. RabbitMQ är mycket populär av flera anledningar:

  1. Det är snabbt och robust.
  2. Det är öppen källkod, men det finns kommersiellt stöd om du vill ha det.
  3. Den körs på ditt operativsystem.
  4. Det är aktivt utvecklat.
  5. Det är slagetestat.

RabbitMQ är implementerat i Erlang, vilket är lite ovanligt, men en av anledningarna till att det är så pålitligt.

förutsättningar

I denna handledning ska jag använda ett lokalt vagrantkluster av tre noder. Om du redan har tre tillgängliga maskiner (virtuellt eller ej) kan du använda dem istället. Var uppmärksam på portar och nätverk.

Installera VirtualBox

Följ instruktionerna för att installera VirtualBox.

Installera Vagrant

Följ anvisningarna för att installera Vagrant

Skapa en RabbitMQ Cluster

Här är en Vagrantfil som kommer att skapa ett lokalt trenodskluster på din maskin. OS är Ubuntu 14.04 (Trusty).

rubin # - * - läge: ruby ​​- * - # vi: set ft = ruby: värdar = "rabbit-1" => "192.168.77.10", "rabbit-2" => "192.168.77.11", "kanin -3 "=>" 192.168.77.12 " Vagrant.configure (" 2 ") do | config | config.vm.box = "trusty64" värds.each_with_index do | (namn, ip), i | rmq_port = 5672 + jag admin_port = 15672 + jag config.vm.define namn gör | maskin | machine.vm.network: private_network, ip: ip config.vm.hostname = "rabbit-% d"% [i + 1] config.vm.network: forwarded_port, gäst: 5672, gäst_ip: ip, värd: rmq_port config. vm.network: forwarded_port, gäst: 15672, guest_ip: ip, värd: admin_port machine.vm.provider "virtualbox" do | v | v.name = namnändändändänden

För att skapa ett tomt kluster, skriv: vagrant upp.

Konfigurera SSH

För att göra det enkelt att ssh in i klusternoderna, skriv: vagrant ssh-config >> ~ / .ssh / config.

Om du skriver: katt ~ / .ssh / config, Du borde se poster för kanin-1, kanin-2 och kanin-3.

Nu kan du ssh till varje virtuell maskin med namn: ssh kanin-1.

Se till att noderna är nåbara med namn

Det enklaste sättet är att redigera filen / etc / hosts. Till exempel, för kanin-1 lägg till adresserna till kanin-2 och kanin-3.

vanligt 192.168.77.11 kanin-2 192.168.77.12 kanin-3

Upprepa processen för alla noder.

Installera RabbitMQ

Jag kommer att använda apt-här för Debian / Ubuntu operativsystem. Om ditt kluster körs på ett annat operativsystem, följ instruktionerna på installationssidan för RabbitMQ.

Observera att ibland är en ganska föråldrad version av RabbitMQ som standard tillgänglig. Om du vill installera det senaste och bästa kan du hämta ett .deb-paket direkt eller lägga till RabbitMQs apt-repository med hjälp av dessa instruktioner.

Den nuvarande versionen av RabbitMQ på Ubuntu 14.04 är 3,2, vilket är tillräckligt bra för våra ändamål. Verifiera själv genom att skriva: apt-cache show rabbitmq-server.

Låt oss fortsätta och installera den på varje maskin:

vanlig sudo apt-få uppdatering sudo apt-get install rabbitmq-server -y

Använd gärna ditt favorit konfigurationshanteringsverktyg som Kock eller Ansible om du föredrar det.

Observera att Erlang installeras först som en förutsättning.

Aktivera RabbitMQ Management Plugin

Förvaltningsprogrammet är verkligen coolt. Det ger dig ett HTTP-baserat API samt ett webb GUI och ett kommandoradsverktyg för att hantera klustret. Så här aktiverar du det:

Vanliga sudo rabbitmq-plugins möjliggör rabbitmq_management

Hämta Management Command-Line Tool

Hämta det från http://192.168.77.10:15672/cli/rabbitmqadmin. Observera att RabbitMQ-dokumentationen är felaktig och berättar att du hämtar från http: //: 15672 / cli /.

Detta är en Python-baserad HTTP-klient för RabbitMQ-hanterings HTTP API. Det är väldigt bekvämt för scripting RabbitMQ-kluster.

Grundläggande RabbitMQ Concepts

RabbitMQ implementerar AMQP 0.9.1-standarden (Advanced Message Queue Protocol). Observera att det redan finns en AMQP 1.0-standard och RabbitMQ har ett plugin för att stödja det, men det anses vara en prototyp på grund av otillräcklig användning i verkligheten.

I AMQP-modellen skickar utgivare meddelanden till en meddelandemäklare (RabbitMQ är meddelandemäklare i detta fall) via en utbyte. Meddelandemäklaren distribuerar meddelandena till köer baserat på metadata som är associerade med meddelandet. Konsumenterna förbrukar meddelanden från köer. Meddelanden kan eller kanske inte erkännas. RabbitMQ stöder en mängd olika programmeringsmodeller utöver dessa begrepp som arbetsköer, publicera-prenumerera och RPC.

Hantera ditt kluster

Det finns tre skript som används för att hantera klustret. Kaninmq-serverns skript startar en RabbitMQ-server (starta den). Kaninmqlt används för att styra klustret (stopp, återställ, klusternoder tillsammans och få status). Kaninmqadmin, som du hämtade tidigare, används för att konfigurera och administrera klustret (deklarera vhosts, användare, utbyten och köer). Skapa ett kluster innebär bara rabbitmq-server och rabbitmqctl.

Låt oss börja rabbitmq-servern som en tjänst (daemon) på var och en av våra värdar kanin-1, kanin-2 och kanin-3.

vanlig sudo service rabbitmq-server start

Detta startar både Erlang VM och RabbitMQ-applikationen om noden är nere. För att verifiera att den körs ordentligt, skriv:

vanlig sudo rabbitmqctl cluster_status

Utsignalen ska vara (för kanin-1):

klättrad status för nod "kanin @ kanin-1" ... [noder, [skiva, ['kanin @ rabbit-1']], running_nodes, ['kanin @ rabbit-1'], partitioner ,[]]… Gjort.

Det betyder att noden inte är klustrad med några andra noder än och det är en skivkod. Det körs också som du kan se att det visas i listan running_nodes.

För att stoppa servern ska du utfärda följande kommando:

vanlig sudo rabbitmqctl stop_app

Därefter om du kontrollerar klusterstatusen:

vanlig sudo rabbitmqctl cluster_status

Utgången ska vara:

vanlig klusterstatus för nod "kanin @ kanin-1" ... [noder, [skiva, ['kanin @ kanin-1']]].

Inga fler löpande noder.

Du kan upprepa processen för de andra noderna (kanin-2 och kanin-3) och se till att de bara känner sig själva.

Erlangkakan

Innan du kan skapa ett kluster måste alla noder i klustret ha samma cookie. Kakan är en fil som Erlang runtime använder för att identifiera noder. Den ligger i /var/lib/rabbitmq/.erlang.cookie. Kopiera bara innehållet från kanin-1 till kanin-2 och kanin-3.

Clustering Noder Tillsammans

Att gruppera dessa separata noder i ett sammanhängande kluster tar lite arbete. Här är proceduren:

  • Har en enda nod köra (t ex kanin-1).
  • Stoppa en annan nod (t ex kanin-2).
  • Återställ den stoppade noden (kanin-2).
  • Kluster den andra noden till rotknutpunkten.
  • Starta den stoppade noden.

Nu gör vi det. ssh till kanin-2 och kör följande kommandon:

ren sudo rabbitmqctl stop_app sudo rabbitmqctl återställ sudo rabbitmqctl join_cluster kanin @ kanin-1

Skriv nu: sudo rabbitmqctl cluster_status.

Utgången ska vara:

"klientstatus för nod" kanin @ kanin-2 "... [noder, [[skiva, [" kanin @ kanin-1 "," kanin @ kanin-2 "]] ... Utfört. Som du kan se båda noderna är nu grupperade. Om du upprepar detta på kanin-1 får du följande resultat:

Klientstatus för nod "kanin @ kanin-1" ... [noder, [skiva, ["kanin @ kanin-1", "kanin @ kanin-2"], running_nodes, ['kanin @ kanin- 1 '], partitioner, [] ... gjort. "

Nu kan du börja kanin-2.

vanlig sudo rabbitmqctl start_app

Om du kontrollerar statusen igen kör båda noderna:

vanlig klusterstatus för nod "kanin @ kanin-2" ... [noder, [skiva, ["kanin @ kanin-1", "kanin @ kanin-2"]], running_nodes, ['kanin @ kanin -1 ',' kanin @ kanin-2 '], partitioner, []] gjort.

Observera att båda noderna är skivnoder, vilket innebär att de lagrar sina metadata på skivan. Låt oss lägga till kanin-3 som en RAM-nod. ssh till kanin-3 och utfärda följande kommandon:

ren sudo rabbitmqctl stop_app sudo rabbitmqctl återställ sudo rabbitmqctl join_cluster --ram kanin @ kanin-2 sudo rabbitmqctl start_app

Kontrollera status visar:

klättrad status för nod "kanin @ kanin-3" ... [noder, [skiva, ["kanin @ kanin-2", "kanin @ kanin-1"], ram, ['kanin @ kanin-3 ']], running_nodes, [' rabbit @ rabbit-1 ',' kanin @ kanin-2 ',' kanin @ kanin-3 '], partitioner, []].

Alla klusternoder körs. Skivnodderna är kanin-1 och kanin-2, och RAM-noden är kanin-3.

grattis! Du har ett fungerande RabbitMQ-kluster.

Real-World Komplikationer

Vad händer om du vill ändra din klusterkonfiguration? Du måste använda kirurgisk precision när du lägger till och tar bort noder från klustret.

Vad händer om en nod inte startas om än, men du försöker fortsätta stop_app, återställa och start_app? Tja, kommandot stop_app kommer uppenbarligen att lyckas och återkommer "done", även om målnoden är nere. Det efterföljande återställningskommandot misslyckas dock med ett otäckt meddelande. Jag tillbringade mycket tid att skrapa mitt huvud och försökte räkna ut det, för jag antog problemet var något konfigurationsalternativ som endast påverkades.

En annan gotcha är att om du vill återställa den sista skivnoden, måste du använda force_reset. Att försöka räkna ut i det allmänna fallet som noden var den sista skivnoden är inte trivial.

RabbitMQ stöder också kluster via konfigurationsfiler. Det här är bra när dina skivnoder är uppe, eftersom omstartade RAM-noder bara kommer att kluster baserat på config-filen utan att du måste klargöra dem explicit. Återigen flyger det inte när du försöker återställa ett brutet kluster.

Pålitlig RabbitMQ Clustering

Det kommer ner till detta: Du vet inte vilken var den sista skivnoden att gå ner. Du känner inte till klustermetadata för varje nod (det gick kanske ner när du återställde). För att starta alla noder använder jag följande algoritm:

  • Starta alla noder (åtminstone den sista skivnoden ska kunna starta).
  • Om inte ens en enda nod kan börja, är du sladdad. Bara borra ut.
  • Håll koll på alla noder som misslyckades med att starta.
  • Försök att starta alla misslyckade noder.
  • Om några noder misslyckades med att starta andra gången, är du sladdad. Bara borra ut.

Denna algoritm kommer att fungera så länge som din sista skivkod är fysiskt OK.

När alla klusternoder är uppe, kan du omkonfigurera dem (kom ihåg att du inte är säker på vad som är klustermetadata för varje nod). Nyckeln är att force_reset varje nod. Detta säkerställer att spår av tidigare klusterkonfiguration raderas från alla noder. Först gör det för en skiva nod:

vanligt stopp_app force_reset start_app

Sedan för varje annan nod (antingen skiva eller RAM):

plain stop_app force_reset join_cluster [lista med skivnoder] start_app

Styra ett kluster avlägset

Du kan SSH i varje lådan och utföra ovanstående steg på varje lådan manuellt. Det fungerar, men det blir gammalt riktigt snabbt. Det är också opraktiskt om du vill bygga och riva ner ett kluster som en del av ett automatiserat test.

En lösning är att använda Fabric. En seriös gotcha jag stötte på är att när jag utförde byggklusteralgoritmen manuellt fungerade det perfekt, men när jag använde Fabric misslyckades det mystiskt. Efter lite debugging såg jag att knutpunkterna började framgångsrikt, men när jag försökte stop_app var knutpunkterna nere. Det här visade sig vara en Fabric newbie misstag från min sida. När du utfärdar ett fjärrkommando med Tyg, startar det ett nytt skal på fjärrmaskinen. När kommandot är klart stängs skalet och skickar en SIGHUP (Hang-up-signal) till alla dess processer, inklusive Erlang-noden. Att använda Nohup tar hand om det. Ett annat starkare alternativ är att köra RabbitMQ som en tjänst (daemon).

Administrera ett kluster programmatiskt

Administration innebär att skapa virtuella värdar, användare, utbyten och köer, inställningsbehörigheter och bindande köer till utbyten. Det första du bör göra om du inte redan har installerat hanteringsprogrammen. Jag är inte säker på varför du måste aktivera det själv. Den ska vara aktiverad som standard.

Webben-användargränssnittet är fantastiskt och du borde definitivt bekanta dig med det. För att administrera ett kluster på distans finns det ett RESTful Management API som du kan använda. Det finns också ett Python kommandoradsverktyg som heter rabbitmqadmin som kräver Python 2.6+. Att använda kaninmqadmin är ganska enkelt. Det enda problemet jag fann är att jag bara kunde använda standardgästkontot för att administrera klustret. Jag skapade en annan administratörs användare som heter "admin", ställer in sina behörigheter till alla (konfigurera / läsa / skriva) och gav den taggen "administratör" (ytterligare krav på hanterings API), men jag fortsatte att få tillståndsfel.

I Elmer-projektet kan du ange en klusterkonfiguration som en Python-datastruktur (se sample_config.py) och ställa in allt för dig.

Start-poäng

  1. RabbitMQ är coolt.
  2. Cluster admin historien är inte lufttät.
  3. Programmatisk administration är nyckeln.
  4. Tyg är ett fantastiskt verktyg för fjärrkontroll av flera Unix-lådor.