wake-up-neo.com

RabbitMQ und Beziehung zwischen Kanal und Verbindung

Der RabbitMQ Java client hat die folgenden Konzepte:

  • Connection - eine Verbindung zu einer RabbitMQ-Serverinstanz
  • Channel - ???
  • Consumer-Thread-Pool - Ein Pool von Threads, die Nachrichten aus den RabbitMQ-Serverwarteschlangen verbrauchen
  • Queue - eine Struktur, die Nachrichten in der Reihenfolge FIFO enthält

Ich versuche, die Beziehung und vor allem die Assoziationen zwischen ihnen zu verstehen.

  1. Ich bin mir immer noch nicht ganz sicher, was ein Channel ist, abgesehen von der Tatsache, dass dies die Struktur ist, über die Sie veröffentlichen und konsumieren und die über eine offene Verbindung erstellt wird. Wenn mir jemand erklären könnte, was der "Kanal" darstellt, könnte dies helfen, ein paar Dinge zu klären.
  2. Wie ist die Beziehung zwischen Channel und Queue? Kann derselbe Kanal für die Kommunikation mit mehreren Warteschlangen verwendet werden oder muss er 1: 1 sein?
  3. Welche Beziehung besteht zwischen der Warteschlange und dem Verbraucherpool? Können mehrere Verbraucher dieselbe Warteschlange abonnieren? Können mehrere Warteschlangen von demselben Verbraucher verwendet werden? Oder ist das Verhältnis 1: 1?

Vielen Dank im Voraus für jede Hilfe hier!

153
user1768830
  1. Eine Connection stellt eine echte TCP Verbindung zum Nachrichtenbroker dar, während eine Channel eine virtuelle Verbindung (AMPQ-Verbindung) innerhalb der Verbindung ist Sie können beliebig viele (virtuelle) Verbindungen in Ihrer Anwendung verwenden, ohne den Broker mit TCP Verbindungen zu überlasten.

  2. Sie können für alles eine Channel verwenden. Wenn Sie jedoch mehrere Threads haben, wird empfohlen, für jeden Thread eine andere Channel zu verwenden.

    Channel-Thread-Sicherheit in Java Client API Guide :

    Kanalinstanzen können sicher von mehreren Threads verwendet werden. Anforderungen in einen Channel werden serialisiert, wobei jeweils nur ein Thread einen Befehl auf dem Channel ausführen kann. Trotzdem sollten Anwendungen es vorziehen, einen Kanal pro Thread zu verwenden, anstatt denselben Kanal über mehrere Threads hinweg zu teilen.

    Es gibt keine direkte Beziehung zwischen Channel und Queue. Eine Channel wird verwendet, um AMQP-Befehle an den Broker zu senden. Dies kann die Erstellung einer Warteschlange oder ähnliches sein, aber diese Konzepte sind nicht miteinander verbunden.

  3. Jede Consumer wird in einem eigenen Thread ausgeführt, der aus dem Consumer-Thread-Pool zugewiesen wurde. Wenn mehrere Konsumenten dieselbe Warteschlange abonniert haben, verwendet der Broker Round-Robin, um die Nachrichten gleichmäßig zwischen ihnen zu verteilen. Siehe Tutorial zwei: "Warteschlangen" .

    Es ist auch möglich, dieselbe Consumer an mehrere Warteschlangen anzuhängen. Sie können Verbraucher als Rückruf verstehen. Diese werden jedes Mal aufgerufen, wenn eine Nachricht in einer Warteschlange eintrifft, an die der Verbraucher gebunden ist. Für den Fall des Java Client, jeder Consumer hat eine Methode handleDelivery(...), die die Rückrufmethode darstellt. Was Sie normalerweise tun, ist Unterklasse DefaultConsumer und überschreiben handleDelivery(...). Hinweis: Wenn Sie dieselbe Consumer-Instanz an mehrere Warteschlangen anhängen, wird diese Methode von verschiedenen Threads aufgerufen. Achten Sie daher bei Bedarf auf die Synchronisierung.

173
Bengt

Ein gutes konzeptionelles Verständnis dessen, was das AMQP-Protokoll "unter der Haube" tut, ist hier nützlich. Ich würde vorschlagen, dass die Dokumentation und API, die AMQP 0.9.1 für die Bereitstellung ausgewählt hat, dies besonders verwirrend macht. Daher ist die Frage selbst eine, mit der sich viele Menschen auseinandersetzen müssen.

TL; DR

Eine Verbindung ist der physische ausgehandelte TCP Socket mit dem AMQP-Server. Bei ordnungsgemäß implementierten Clients ist einer dieser Sockets pro Anwendung thread-sicher und kann zwischen Threads geteilt werden .

Ein Kanal ist eine einzelne Anwendungssitzung auf der Verbindung. Ein Thread wird eine oder mehrere dieser Sitzungen haben. AMQP-Architektur 0.9.1 besagt, dass diese nicht unter Threads geteilt werden dürfen und geschlossen/zerstört werden sollten, wenn der Thread, der sie erstellt hat, damit fertig ist. Sie werden auch vom Server geschlossen, wenn verschiedene Protokollverletzungen auftreten.

Ein consumer ist ein virtuelles Konstrukt, das das Vorhandensein einer "Mailbox" auf einem bestimmten Kanal darstellt. Die Verwendung eines Verbrauchers weist den Broker an, Nachrichten von einer bestimmten Warteschlange an diesen Kanalendpunkt zu senden.

Verbindungsdaten

Erstens, wie andere richtig ausgeführt haben, ist eine Verbindung das Objekt, das die tatsächliche TCP Verbindung zum Server darstellt Verbindungen werden in AMQP auf Protokollebene angegeben, und die gesamte Kommunikation mit dem Broker erfolgt über eine oder mehrere Verbindungen.

  • Da es sich um eine tatsächliche TCP Verbindung handelt, verfügt sie über eine IP-Adresse und eine Anschlussnummer.
  • Protokollparameter werden im Rahmen des Verbindungsaufbaus auf Client-Basis ausgehandelt (ein Prozess, der als Handshake bezeichnet wird.
  • Es soll langlebig sein; Es gibt nur wenige Fälle, in denen der Verbindungsabbau Teil des Protokolldesigns ist.
  • Aus OSI-Sicht befindet es sich wahrscheinlich irgendwo in der Nähe von Layer 6
  • Heartbeats können eingerichtet werden, um den Verbindungsstatus zu überwachen, da TCP nichts an und für sich enthält, um dies zu tun.
  • Es ist am besten, dass ein dedizierter Thread die Lese- und Schreibvorgänge auf dem zugrunde liegenden TCP Socket verwaltet. Die meisten, wenn nicht alle RabbitMQ-Clients tun dies. In dieser Hinsicht sind sie im Allgemeinen thread-sicher.
  • Relativ gesehen ist die Herstellung von Verbindungen (aufgrund des Handshakes) "teuer", aber praktisch spielt dies keine Rolle. Die meisten Prozesse benötigen nur ein Verbindungsobjekt. Sie können jedoch Verbindungen in einem Pool aufrechterhalten, wenn Sie feststellen, dass Sie mehr Durchsatz benötigen, als ein einzelner Thread/Socket bereitstellen kann (mit der aktuellen Computertechnologie unwahrscheinlich).

Channel Facts

Ein Channel ist die Anwendungssitzung, die für jedes Teil Ihrer App geöffnet wird, um mit dem RabbitMQ-Broker zu kommunizieren. Es funktioniert über eine einzige Verbindung und repräsentiert eine Sitzung mit dem Broker.

  • Da es sich um einen logischen Teil der Anwendungslogik handelt, ist jeder Kanal normalerweise in einem eigenen Thread vorhanden.
  • In der Regel teilen sich alle von Ihrer App geöffneten Kanäle eine einzige Verbindung (es handelt sich um Lightweight-Sitzungen, die über der Verbindung ausgeführt werden). Die Verbindungen sind threadsicher, dies ist also in Ordnung.
  • Die meisten AMQP-Operationen finden über Kanäle statt.
  • Aus Sicht der OSI-Schicht sind Kanäle wahrscheinlich in der Nähe von Schicht 7 .
  • Kanäle sind so konzipiert, dass sie vorübergehend sind ; Teil des Entwurfs von AMQP ist, dass der Kanal in der Regel als Reaktion auf einen Fehler geschlossen wird (z. B. erneutes Deklarieren einer Warteschlange mit unterschiedlichen Parametern vor dem Löschen der vorhandenen Warteschlange).
  • Kanäle sollten von Ihrer App nicht gepoolt werden, da sie nur vorübergehend sind.
  • Der Server verwendet eine Ganzzahl, um einen Kanal zu identifizieren. Wenn der Thread, der die Verbindung verwaltet, ein Paket für einen bestimmten Kanal empfängt, teilt er dem Broker mit, zu welchem ​​Kanal/zu welcher Sitzung das Paket gehört.
  • Kanäle sind im Allgemeinen nicht threadsicher, da es keinen Sinn macht, sie unter Threads zu teilen. Wenn Sie einen anderen Thread haben, der den Broker verwenden muss, wird ein neuer Channel benötigt.

Consumer Facts

Ein Consumer ist ein Objekt, das vom AMQP-Protokoll definiert wird. Es ist weder ein Kanal noch eine Verbindung, sondern wird von Ihrer Anwendung als eine Art "Mailbox" zum Löschen von Nachrichten verwendet.

  • "Erstellen eines Verbrauchers" bedeutet, dass Sie dem Broker (über einen Kanal über eine Verbindung) mitteilen, dass Sie Nachrichten über diesen Kanal an Sie senden möchten. Als Antwort registriert der Broker, dass Sie einen Consumer im Channel haben, und beginnt, Nachrichten an Sie zu senden.
  • Jede Nachricht, die über die Verbindung gesendet wird, verweist sowohl auf eine Kanalnummer als auch auf eine Verbrauchernummer. Auf diese Weise weiß der verbindungsverwaltende Thread (in diesem Fall innerhalb der Java API), was mit der Nachricht zu tun ist, und der Thread für die Kanalbehandlung weiß auch, was mit der zu tun ist Botschaft.
  • Die Consumer-Implementierung weist die größte Variationsbreite auf, da sie buchstäblich anwendungsspezifisch ist. In meiner Implementierung habe ich mich dafür entschieden, eine Aufgabe jedes Mal abzuspalten, wenn eine Nachricht über den Consumer eingeht. Ich hatte also einen Thread, der die Verbindung verwaltete, einen Thread, der den Kanal (und damit auch den Verbraucher) verwaltete, und einen oder mehrere Task-Threads für jede Nachricht, die über den Verbraucher zugestellt wurde.
  • Schließen einer Verbindung schließt alle Kanäle der Verbindung. Schließen eines Kanals schließt alle Verbraucher im Kanal. Es ist auch möglich, stornieren einen Verbraucher (ohne den Kanal zu schließen). Es gibt verschiedene Fälle, in denen es sinnvoll ist, eines der drei Dinge zu tun.
  • In der Regel weist die Implementierung eines Verbrauchers in einem AMQP-Client dem Verbraucher einen dedizierten Kanal zu, um Konflikte mit den Aktivitäten anderer Threads oder Codes (einschließlich Veröffentlichung) zu vermeiden.

In Bezug auf das, was Sie unter Consumer-Thread-Pool verstehen, vermute ich, dass Java client etwas Ähnliches tut, wie ich es meinem Client programmiert habe (meiner basierte auf dem .Net-Client, wurde aber stark modifiziert) ).

41
theMayer

Ich habe diesen Artikel gefunden, in dem alle Aspekte des AMQP-Modells erläutert werden, von denen Channel einer ist. Ich fand es sehr hilfreich, mein Verständnis abzurunden

https://www.rabbitmq.com/tutorials/amqp-concepts.html

Einige Anwendungen benötigen mehrere Verbindungen zu einem AMQP-Broker. Es ist jedoch unerwünscht, viele TCP Verbindungen gleichzeitig offen zu halten, da dies Systemressourcen verbraucht und die Konfiguration von Firewalls erschwert. AMQP 0-9-1-Verbindungen werden mit Kanälen gemultiplext Das kann man sich als "schlanke Verbindungen vorstellen, die sich eine einzige TCP Verbindung teilen".

Bei Anwendungen, die mehrere Threads/Prozesse für die Verarbeitung verwenden, wird häufig ein neuer Kanal pro Thread/Prozess geöffnet und keine Kanäle zwischen ihnen geteilt.

Die Kommunikation auf einem bestimmten Kanal ist völlig unabhängig von der Kommunikation auf einem anderen Kanal. Daher enthält jede AMQP-Methode auch eine Kanalnummer, mit der Clients herausfinden, für welchen Kanal die Methode bestimmt ist (und daher beispielsweise, welcher Event-Handler aufgerufen werden muss). .

19
CamW