Hier ist ein gutes konzeptionelles Verständnis der Funktionsweise des AMQP-Protokolls "unter der Haube" hilfreich. Ich würde anbieten, dass die Dokumentation und API, die AMQP 0.9.1 für die Bereitstellung ausgewählt hat, dies besonders verwirrend macht, sodass die Frage selbst eine ist, mit der sich viele Menschen auseinandersetzen müssen.
TL; DR
Eine Verbindung ist der physisch ausgehandelte TCP-Socket mit dem AMQP-Server. Bei ordnungsgemäß implementierten Clients ist eine dieser Anwendungen pro Anwendung threadsicher und kann unter Threads gemeinsam genutzt werden.
Ein Kanal ist eine einzelne Anwendungssitzung für die Verbindung. Ein Thread hat eine oder mehrere dieser Sitzungen. Die AMQP-Architektur 0.9.1 sieht vor, dass diese nicht von Threads gemeinsam genutzt 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 betont haben, a 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 Portnummer.
- Protokollparameter werden im Rahmen des Verbindungsaufbaus pro Client ausgehandelt (ein Prozess, der als Handshake bezeichnet wird) .
- Es ist so konzipiert, dass es langlebig ist ; Es gibt nur wenige Fälle, in denen das Schließen der Verbindung Teil des Protokolldesigns ist.
- Aus OSI-Sicht befindet es sich wahrscheinlich irgendwo in der Nähe von Schicht 6
- Heartbeats können eingerichtet werden, um den Verbindungsstatus zu überwachen, da TCP an und für sich nichts enthält, um dies zu tun.
- Es ist am besten, wenn ein dedizierter Thread 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 threadsicher.
- Relativ gesehen sind Verbindungen "teuer" (aufgrund des Handshakes), aber praktisch spielt dies keine Rolle. Die meisten Prozesse benötigen wirklich 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).
Kanal Fakten
Ein Kanal ist die Anwendungssitzung, die für jeden Teil Ihrer App geöffnet wird, um mit dem RabbitMQ-Broker zu kommunizieren. Es arbeitet über eine einzelne Verbindung und repräsentiert eine Sitzung mit dem Broker.
- Da es einen logischen Teil der Anwendungslogik darstellt, existiert normalerweise jeder Kanal in einem eigenen Thread.
- In der Regel teilen sich alle von Ihrer App geöffneten Kanäle eine einzige Verbindung (dies sind einfache Sitzungen, die über der Verbindung ausgeführt werden). Die Verbindungen sind threadsicher, daher ist dies in Ordnung.
- Die meisten AMQP-Operationen finden über Kanäle statt.
- Aus Sicht der OSI-Schicht befinden sich die 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 normalerweise als Reaktion auf einen Fehler geschlossen wird (z. B. erneutes Deklarieren einer Warteschlange mit verschiedenen Parametern vor dem Löschen der vorhandenen Warteschlange).
- Da sie vorübergehend sind, sollten Kanäle nicht von Ihrer App gepoolt werden.
- 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, verwendet er diese Nummer, um dem Broker mitzuteilen, zu welchem Kanal / welcher Sitzung das Paket gehört.
- Kanäle sind im Allgemeinen nicht threadsicher, da es keinen Sinn macht, sie zwischen Threads zu teilen. Wenn Sie einen anderen Thread haben, der den Broker verwenden muss, wird ein neuer Kanal benötigt.
Verbraucher Fakten
Ein Verbraucher ist ein Objekt, das durch das AMQP-Protokoll definiert ist. Es ist weder ein Kanal noch eine Verbindung, sondern etwas, das Ihre spezielle Anwendung als eine Art "Postfach" 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 Verbraucher im Kanal haben, und beginnt, Nachrichten an Sie zu senden.
- Jede über die Verbindung übertragene Nachricht 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. Dann weiß der Channel-Handling-Thread auch, was mit der Nachricht zu tun ist.
- Die Implementierung von Verbrauchern ist am unterschiedlichsten, da sie buchstäblich anwendungsspezifisch ist. In meiner Implementierung habe ich mich entschieden, jedes Mal eine Aufgabe auszulagern, wenn eine Nachricht über den Verbraucher eingeht. Daher hatte ich 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 über den Verbraucher übermittelte Nachricht.
- Durch das Schließen einer Verbindung werden alle Kanäle der Verbindung geschlossen. Durch das Schließen eines Kanals werden alle Verbraucher auf dem Kanal geschlossen. Es ist auch möglich, einen Verbraucher abzubrechen (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 der Java-Client etwas Ähnliches tut, wie ich meinen Client programmiert habe (meiner basierte auf dem .Net-Client, wurde jedoch stark modifiziert).