Eine Einführung in RabbitMQ – Was ist RabbitMQ?

Warum Rabbit? Was ist MQ? Wie kann es unsere Anwendungen verbessern? Warum sollte ich mehr darüber erfahren wollen? – Das sind Fragen, die ich mir gestellt habe, als ich RabbitMQ zum ersten Mal kennengelernt habe. Mein Name ist Gabor, und ich bin jetzt RabbitMQ-Ingenieur und Berater. Während meiner Arbeit mit RabbitMQ habe ich gelernt, dass selbst erfahrene Kunden diese Fragen stellen.

TL;DR > Besuchen Sie unsere RabbitMQ-Produktseite für Anwendungsfälle, Funktionen und um unsere Experten zu kontaktieren.

Welches Problem löst RabbitMQ?

Bevor wir uns damit beschäftigen, was RabbitMQ ist und wie man es benutzt, lohnt es sich, mehr über die Problemdomäne selbst zu erfahren. Die Kommunikation zwischen verschiedenen Diensten (a.k.a. Computern) ist ein uraltes Problem.

Einerseits gibt es die verschiedenen Protokolle, die die Transportmittel und die Eigenschaften der Kommunikation definieren. Einige Beispiele für solche Protokolle sind SMTP, FTP, HTTP oder WebSockets (um nur einige zu nennen), die alle auf TCP/UDP basieren. Sie befassen sich mit der Formatierung, der Zuverlässigkeit und dem Auffinden des richtigen Empfängers einer Nachricht.

Auf der anderen Seite können wir die Kommunikation aus der Perspektive der Nachricht betrachten. Sie existiert in einem System, dann wird sie zu einem anderen transportiert, wird transformiert, das heißt, sie hat einen Lebenszyklus. Auf dem Weg von einem System zum anderen sollten wir wissen, wo sich die Nachricht befindet und wem sie zu einem bestimmten Zeitpunkt gehört.

Die oben erwähnten Kommunikationsprotokolle können dafür sorgen, dass der Besitz (und der „physische“ Ort) der Nachricht von einem System zum anderen übertragen wird (auch wenn die Ausführung dieser Transaktion einige Zeit in Anspruch nehmen kann). Wir können die Übertragung als eine Transaktion zwischen den beiden Parteien betrachten, solange beide anwesend sind. In den meisten Fällen ist dieser aktive Austausch wünschenswert, z. B. wenn man nach dem Status eines Dienstes fragt und eine zeitnahe und genaue Antwort erwartet. Ein Beispiel aus der physischen Welt wäre ein Telefonanruf:
1) wir beginnen den Anruf,
2) wir warten darauf, dass die andere Partei antwortet,
3) wir führen ein nettes Gespräch,
4) wir legen den Hörer auf.

Es gibt aber auch andere Momente, in denen wir keine Antwort brauchen, sondern nur, dass der Empfänger die Nachricht annimmt und seine Arbeit erledigt. In diesem Fall brauchen wir einen Vermittler, ein anderes System, das die Nachricht (vorübergehend) übernimmt und dafür sorgt, dass die Nachricht ihr Ziel erreicht. Um das Telefonbeispiel noch weiter zu treiben: Der Gesprächspartner ist im Moment nicht erreichbar, also hinterlassen wir eine Sprachnachricht. Der Voicemail-Dienst benachrichtigt den vorgesehenen Empfänger.

Diese asynchrone (verzögerte) Zustellung von Nachrichten ist das, was RabbitMQ bietet. Offensichtlich kann es mehr als ein einfacher Anrufbeantworter, also lassen Sie uns einige der Optionen, die es bietet, weiter unten erkunden

(Wenn Sie daran interessiert sind, mehr über die Geschichte von RabbitMQ zu erfahren, empfehle ich das erste Kapitel von „RabbitMQ in Action“ von Alvaro Videla und Jason Williams. Es wird die Antwort auf die Frage geben, warum es nach Kaninchen benannt ist).

RabbitMQ ist eine freie, quelloffene und erweiterbare Message-Queuing-Lösung. Es ist ein Message Broker, der AMQP (Advanced Message Queuing Protocol) versteht, aber auch mit anderen gängigen Messaging-Lösungen wie MQTT verwendet werden kann. Er ist hochverfügbar, fehlertolerant und skalierbar. Es ist in Erlang OTP implementiert, einer Technologie, die auf den Aufbau stabiler, zuverlässiger, fehlertoleranter und hoch skalierbarer Systeme zugeschnitten ist, die von Haus aus in der Lage sind, eine sehr große Anzahl gleichzeitiger Operationen zu bewältigen, wie es bei RabbitMQ und anderen Systemen wie WhatsApp, MongooseIM, um nur einige zu nennen, der Fall ist.

Auf einer sehr hohen Ebene ist es eine Middleware-Schicht, die es verschiedenen Diensten in Ihrer Anwendung ermöglicht, miteinander zu kommunizieren, ohne sich Gedanken über den Verlust von Nachrichten zu machen, und dabei unterschiedliche Anforderungen an die Dienstqualität (QoS) zu erfüllen. Es ermöglicht auch ein feinkörniges und effizientes Nachrichten-Routing, das eine weitgehende Entkopplung von Anwendungen ermöglicht.

Anwendungsfälle

Um die Vielseitigkeit von RabbitMQ zu demonstrieren, werden wir drei Fallstudien verwenden, die zeigen, wie RabbitMQ als Black-Box-Managed-Service-Ansatz, als ein Ansatz, der sich eng in die Anwendung integriert und eine gut funktionierende Micro-Service-Architektur ermöglicht, oder als Gateway zu anderen Legacy-Projekten geeignet ist.

RabbitMQ als allgemeiner Message-Bus

Wenn ein monolithisches System in einzelne Subsysteme zerlegt wird, ist eines der größten Probleme, die gelöst werden müssen, die Frage nach der zu verwendenden Kommunikationstechnologie. Eine Lösung wie Mulesoft oder MassTransit kann Dienste „verkabeln“, indem sie HTTP-Listener und -Sender deklariert. Diese Art von Lösung behandelt RabbitMQ als eine Blackbox, ist aber dennoch in der Lage, die Fähigkeiten von RabbitMQ zu nutzen. Als Beispiel für eine direkte Kommunikation wollen wir HTTP verwenden, um die einzelnen Dienste zu „verbinden“. Obwohl es eine gut unterstützte und solide Wahl ist, hat es einige Nachteile:
1) Die Erkennung von Diensten ist nicht gelöst. Eine mögliche Lösung ist die Verwendung von DNS. Wenn das System skaliert und wächst, steigt auch die Komplexität der Suche und des Ausgleichs dieser Last. RabbitMQ kann die erhöhte Komplexität der Lösung abmildern.
2) Die Kommunikation ist flüchtig. Nachrichten sind anfällig dafür, auf der Netzwerkebene verworfen oder dupliziert zu werden. Wenn ein Dienst vorübergehend nicht verfügbar ist, schlägt die Zustellung fehl.

RabbitMQ kann in beiden Fällen helfen, indem es Nachrichtenwarteschlangen als Transportmittel nutzt. Dienste können Nachrichten veröffentlichen und konsumieren, wodurch die End-to-End-Zustellung von Nachrichten von der Verfügbarkeit des Zieldienstes entkoppelt wird. Wenn ein konsumierender Dienst vorübergehend nicht verfügbar ist, wird die Nachricht im Gegensatz zu HTTP sicher gepuffert und in RabbitMQ aufbewahrt und schließlich zugestellt, wenn der Dienst wieder online ist.

Auch die Auffindbarkeit wird vereinfacht. Alles, was wir wissen müssen, ist, wo RabbitMQ ist und wie der Name der Warteschlange lautet. Obwohl es so aussieht, als würde das Problem neu erfunden, ist es skalierbar. Der Name der Warteschlange dient als Adresse des Dienstes. Der Abruf von Nachrichten aus den Warteschlangen durch die einzelnen Dienste bietet eine Möglichkeit zur Skalierung, d. h. jede Warteschlange kann mehrere Abrufe bedienen und die Last ausgleichen. Es besteht keine Notwendigkeit, die bereits in die Dienste eingebaute Warteschlangenkonfiguration zu ändern.

Diese mäßig statische Warteschlangenkonfiguration drängt RabbitMQ in eine Middleware-Schicht, in der ein solides Design langfristig eine stabile Dienstqualität garantieren kann.

RabbitMQ als fortschrittliche Routing-Schicht für Mikrodienste

Am anderen Ende des Spektrums steht eine Architektur, die flüssiger ist und sich an die sich ständig ändernden Bedürfnisse vieler Mikrodienste anpasst. Was RabbitMQ in dieser Umgebung auszeichnet, sind die sehr leistungsfähigen Routing-Fähigkeiten, die es bietet.

Die Routing-Logik ist in verschiedenen (sogenannten) Exchange-Typen implementiert, die von der Anwendung bei Bedarf dynamisch erstellt werden können. Die Zieldienste erstellen die Warteschlangen, von denen sie konsumieren wollen, und binden sie dann an die Austauschvorgänge, indem sie ein Muster für die Schlüssel angeben, die die Herausgeber bei der Veröffentlichung der Nachricht verwenden können. (Stellen Sie sich diese Schlüssel als Metadaten vor, die die Vermittlungsstellen verwenden können, um die Nachrichten an eine oder mehrere Warteschlangen weiterzuleiten und zuzustellen.)

Die Weiterleitungslogik ist in verschiedenen (sogenannten) Vermittlungsstellentypen implementiert, die bei Bedarf dynamisch von der Anwendung erstellt werden können. Die Zieldienste erstellen die Warteschlangen, aus denen sie konsumieren möchten, und binden sie dann an die Austausche, indem sie ein Muster für die Schlüssel angeben, die die Verleger bei der Veröffentlichung der Nachricht verwenden können. (Betrachten Sie diese Schlüssel als Metadaten, die die Exchanges verwenden können, um die Nachrichten an eine oder mehrere Warteschlangen weiterzuleiten und zuzustellen.)

RabbitMQ bietet vier nützliche Exchange-Typen, die die meisten Anwendungsfälle für Messaging abdecken:
1) Direkter Austausch. Damit wird die eingehende Nachricht an jede Warteschlange zugestellt, deren Bindungsschlüssel genau mit dem Routing-Schlüssel der Nachricht übereinstimmt. Wenn Sie die Warteschlangen mit dem Namen der Warteschlange als Routing-Schlüssel binden, können Sie sich das wie eine Eins-zu-eins-Zustellung von Nachrichten vorstellen. Es ist einfach, dieselbe Nachricht an mehrere Warteschlangen zuzustellen, indem man die Bindungsschlüssel für mehrere Warteschlangen verwendet.
2) Themenaustausch. Damit wird die eingehende Nachricht an jede Warteschlange zugestellt, deren Wildcard-Bindungsschlüssel mit dem Routing-Schlüssel der veröffentlichten Nachricht übereinstimmt. Bindungsschlüssel können Wildcard-Matching-Kriterien für einen zusammengesetzten Routing-Schlüssel enthalten. (z. B. passt der Bindungsschlüssel logs.*.error zu den Routing-Schlüsseln logs.accounting.error und logs.ui.error). Dies ermöglicht es uns, einfache Dienste zu schreiben, bei denen die Logik in sich geschlossen ist und die Nachricht durch die „Magie“ von RabbitMQ bei den richtigen Diensten ankommt.
3) Fanout-Austausch. Einige Nachrichten müssen an alle Warteschlangen zugestellt werden. Hier kann ein Fanout-Exchange verwendet werden, anstatt eine aufwendige Multicast-Logik in der Anwendung zu schreiben. Bei einem RabbitMQ-Fanout-Exchange bindet jeder Dienst die entsprechende Warteschlange an den Exchange, ohne dass ein Bindungsschlüssel angegeben werden muss – alles geschieht automatisch. Wenn ein Bindungsschlüssel angegeben wird, ignoriert der Fanout-Exchange diesen einfach und leitet Nachrichten an alle Queues weiter, die an ihn gebunden sind.
4) Austausch von Headern. Dieser Austausch nutzt die Struktur von AMQP-Nachrichten und ist in der Lage, komplexes Routing auf der Grundlage der Header (einschließlich benutzerdefinierter Header) der AMQP-Nachricht durchzuführen. Header sind Metadaten, die an jede über AMQP gesendete Nachricht angehängt werden.

Neben dem Austausch gibt es weitere nützliche Funktionen in RabbitMQ, die die Implementierung von sehr komplexer Nachrichtenlogik ermöglichen. Einige der wichtigsten Funktionen sind:
1) Benutzerdefinierte Plug-ins. RabbitMQ ist erweiterbar, indem es seinen Benutzern erlaubt, Plug-ins hinzuzufügen. Fast jeder Aspekt von RabbitMQ ist anpassbar, einschließlich der Verwaltung, Authentifizierung und Autorisierung, Back-up-Lösungen und Clustering.
2) Clustering. Wenn ein einzelner RabbitMQ-Server nicht ausreicht, können mehrere RabbitMQ-Broker verbunden werden, um zusammenzuarbeiten und das System zu skalieren. Dies kann RabbitMQ in die Lage versetzen, mehr Nachrichten zu verarbeiten oder die Widerstandsfähigkeit gegenüber Fehlern zu erhöhen.
3) Quality of Service tuning. Die zeitkritische Zustellung von Nachrichten kann unterstützt werden, indem ein TTL-Wert (Time-to-Live) entweder an die Nachricht oder die Warteschlange angehängt wird. Nachrichten, deren Zeit abgelaufen ist, können automatisch an eine Warteschlange mit toten Buchstaben zugestellt werden. Die Kombination von gewöhnlicher Routing-Logik und diesen zusätzlichen Funktionen kann zu sehr fortschrittlichen Routing-Logiken führen. Eine weitere nützliche Funktion ist die Verwendung von Prioritätswarteschlangen, in denen der Herausgeber jeder Nachricht eine Prioritätsstufe zuweisen kann. Es ist auch möglich, die Anzahl der unbestätigten Nachrichten zu begrenzen, was ein Leistungstuning der konsumierenden Dienste ermöglicht. In diesem Fall wendet RabbitMQ einen Gegendruck-Mechanismus an.

RabbitMQ integriert in Legacy-Systeme

Im vorherigen Anwendungsfall habe ich die Möglichkeit erwähnt, Plug-ins zu verwenden, um die Funktionalität von RabbitMQ zu erweitern. Dieses mächtige Feature erlaubt es RabbitMQ, als Vermittlungsschicht zwischen Ihren nativen (AMQP-fähigen) RabbitMQ-Diensten und anderen Legacy-Anwendungen zu fungieren. Einige bemerkenswerte Beispiele sind:
1) Verwendung von RabbitMQ als MQTT-Broker durch einfaches Aktivieren eines Plug-ins. Dies öffnet die Landschaft für viele IoT-Technologien.
2) RabbitMQ’s JMS (Java Message Service) Plug-in, welches RabbitMQ erlaubt, mit jeder JMS-fähigen Messaging-Lösung zu kommunizieren.
3) Wenn Ihre Anwendung ein proprietäres Protokoll für die Kommunikation verwendet, ist es möglich, ein benutzerdefiniertes Plug-in zu entwickeln, um sich mit solchen Diensten zu verbinden.

Abschluss

Wie die oben genannten Beispiele zeigen, gibt es kaum etwas, mit dem RabbitMQ nicht kommunizieren kann. Aber wie alles im Leben hat auch das seinen Preis. Obwohl die Konfiguration von RabbitMQ meist einfach ist, kann die schiere Anzahl der Funktionen manchmal überwältigend sein. Wenn Sie Probleme mit dem Design, der Implementierung oder dem Support Ihrer RabbitMQ-Broker haben, wenden Sie sich bitte an unser Expertenteam hier. Oder wenn Sie Ihre Karriere in einer der gefragtesten Technologien starten möchten, melden Sie sich für unseren 3-tägigen RabbitMQ-Trainingskurs an.

Debugging von RabbitMQ

Wollen Sie ein intuitives System, das Ihnen die Überwachung und Wartung Ihres RabbitMQ erleichtert? Holen Sie sich jetzt Ihre kostenlose 45-Tage-Testversion von WombatOAM.

Unsere RabbitMQ-Funktionsseite