Nachrichtenverarbeitungsknoten und Parser müssen in einer Multi-Thread-Umgebung mit mehreren Instanzen arbeiten. Es können viele Knotenobjekte oder Parserobjekte, jedes mit beliebigen Syntaxelementen, vorhanden sein und viele Threads, die Methoden für diese Objekte ausführen. Das Nachrichtenbrokerdesign stellt sicher, dass ein Nachrichtenobjekt und alle Objekte, die es besitzt, nur von dem Thread verwendet werden, der die Nachricht im Verlauf des Nachrichtenflusses empfängt und verarbeitet.
Eine Instanz eines Nachrichtenflussverarbeitungsknotens wird von allen Threads, die den Nachrichtenfluss bedienen, in dem der Knoten definiert ist, gemeinsam genutzt. Eine Instanz eines Parser wird nur von einem einzigen Nachrichtenfluss-Thread verwendet.
Eine benutzerspezifische Erweiterung muss sich an dieses Modell halten und sollte die Verwendung von globalen Daten oder Ressourcen vermeiden, die Semaphoren erfordern, um den Zugriff über Threads hinweg zu serialisieren. Eine solche serielle Verarbeitung kann Leistungsengpässe verursachen.
Implementierungsfunktionen einer benutzerspezifischen Erweiterung müssen simultan verwendbar sein, und alle Funktionen, die sie aufrufen, müssen es ebenfalls sein. Alle Dienstprogrammfunktionen einer benutzerspezifischen Erweiterung sind vollständig simultan verwendbar.
Auch wenn eine benutzerspezifische Erweiterung bei Bedarf zusätzliche Threads erstellen kann, ist es entscheidend, dass derselbe Thread die Steuerung nach Abschluss einer Implementierungsfunktion an den Broker zurückgibt. Geschieht dies nicht, wird die Integrität des Brokers verletzt und sind unvorhersehbare Ergebnisse die Folge.
Das folgende Beispiel eines Nachrichtenflusses soll Ihnen helfen, einige der Threading-Besonderheiten, die Sie beim Entwerfen und Implementieren eigener benutzerspezifischer Knoten beachten sollten, zu verstehen. Dazu wird ein benutzerspezifischer Empfangsknoten als Beispiel verwendet.
Ein Nachrichtenfluss kann so konfiguriert werden, dass er in mehreren Threads ausgeführt wird. Dies wird durch die Anzahl der Empfangsknoten im Nachrichtenfluss und durch den Wert der Eigenschaft 'additionalInstances' des Nachrichtenflusses festgelegt. Diese beiden Elemente bestimmen die maximale Kapazität des Thread-Pools, den der Nachrichtenfluss verwenden kann. Falls für Ihren Nachrichtenfluss bestimmte Verarbeitungsanforderungen gelten, die eine Einzelthreadverarbeitung erforderlich machen, müssen Sie deshalb sicherstellen, dass dies der Fall ist.
Die effizienteste Methode, um zu verhindern, dass die Eingabewarteschlange zu einem Engpass wird, besteht darin, dem Broker über die Eigenschaft additionalInstances zu erlauben, zusätzliche Kopien des Nachrichtenflusses in separaten Threads zu starten. Bei separaten Threads ist es jedoch möglich, dass eine Parallelverarbeitung von Nachrichten aus der Nachrichtenwarteschlange stattfindet. Daher sollten Sie diese Methode nur verwenden, wenn die Reihenfolge, in der die Nachrichten verarbeitet werden, nicht wichtig ist.
Threads werden als Ergebnis der Erstellung und des Betriebs eines Empfangsknotens erstellt. Ein Thread steht immer als aktiver oder inaktiver Thread im Thread-Pool. Inaktive Threads bleiben so lange im Pool stehen, bis sie von einem Empfangsknoten zugeteilt werden oder der Broker heruntergefahren wird.
Die folgende Abbildung zeigt die Threadzuordnung in einem Nachrichtenfluss.
Threadzuordnung in einem Nachrichtenfluss
Als erstes wird Thread 1 angefordert (A) und wartet auf Nachrichten. Sobald eine Nachricht ankommt (B), gibt Thread 1 sie weiter und teilt Thread 2 zu. Thread 2 empfängt sofort eine Nachricht (C), gibt sie weiter und teilt Thread 3 zu, der auf eine Nachricht wartet (D). Thread 1 beendet die Verarbeitung (E) und wird zurück in den Thread-Pool gestellt. Dann empfängt Thread 3 eine Nachricht (F), teilt Thread 1 zu und gibt die Nachricht weiter. Thread 1 wartet jetzt darauf, dass eine Nachricht in der Warteschlange ankommt (G).
Es lohnt sich ein genauer Blick auf den Punkt H. An dieser Stelle im Nachrichtenfluss erhält Thread 1 eine Nachricht, kann aber keine Zuteilung vornehmen, weil alle anderen Threads gerade aktiv sind. Die Nachricht wird weitergegeben.
Nachdem diese Nachricht weitergegeben wurde, beendet Thread 2 die Verarbeitung (I), empfängt eine neue Nachricht aus der Warteschlange und gibt diese neue Nachricht weiter. Dann beendet Thread 3 die Verarbeitung (J) und wird zurück in den Pool gestellt. Anschließend beendet auch Thread 2 die Verarbeitung (K). Da Thread 1 nach Abschluss der Verarbeitung keine Zuteilung vornehmen konnte (L), kann er nicht zurück in den Thread-Pool gestellt werden, obwohl keine Nachrichten in der Warteschlange enthalten sind, sondern wartet stattdessen darauf, dass eine Nachricht in der Warteschlange ankommt.