Messaging

Das Haupt-Feature von devel.one ist die Verwendung von Messages.

Mit Message meinen wir hier eine spezialisierte Klasse, die aus zwei Teilen besteht: Einem Umschlag (Envelope), welcher die Eigenschaften der Message bestimmt, sowie die Nutzdaten, bestehend aus einem oder mehreren Records.

Messages werden nicht irgendwo gespeichert, wenn der Empfänger nicht verfügbar ist. Sie sind sehr kurzlebig, meist existieren sie nicht mal eine Millisekunde. Wir verwenden indirektes Messaging über Warteschlangen, und auch kein Publish & Subscribe Mechanismus.

Messages sind immer gerichtet, d.h. sie haben einen Absender und einen Empfänger. Beide (Absender und Empfänger) haben eine Adresse, ähnlich einer Postadresse. Wir unterscheiden den Request (ich möchte etwas haben, schicke mir eine Antwort) von der <>Notifikation (eine Info für dich). Das dient nur dem besseren Verständnis des Zwecks einer Message. Letztlich unterscheiden sich die beiden Message-Typen nur in einem Bit (wantAnswer). Im Fehlerfall (auf dem Weg, bei der Zustellung, bei der Verarbeitung beim Empfänger, bei Exceptions etc.) wird die Nachricht sowieso zurückgeschickt. Das Zurückschicken der Nachricht wird vom System automatisch gemacht. Der Empfänger füllt nur einen Result-Code und optional einen Result-Text (für das Logging). Ob eine Nachricht vom Empfänger behandelt wurde, kann der Sender leicht prüfen, da in diesem Fallse die Nachrichten mit dem Result-Code NOT_HANDLED versehen werden. Ist dieser Code in der Antwort vorhanden, wurde der Resultcode vom Emfänger nicht gesetzt (nicht gut!) bzw. die Nachricht nicht gehandelt (State Machines!).

Mittels der Adresse kann das System den Empfänger der Nachricht direkt finden, weitere Angaben zur Zustellung sind nicht nötig. Dabei kann sich der Empfänger auch auf einem anderen NODE innerhalb des Peer-to-Peer-Netzwerks befinden. Für mehr Informationen über Messages siehe hier.

Die Empfänger von Messages sind im System hierachisch gegliedert:

  • Targets

    Targets sind die Bausteine, welche Messages empfangen und verarbeiten können. Sie sind sehr einfach aufgebaut, und haben eine ID, die Target-ID (TID).

    Targets bekommen die Nachrichten immer in dem selben Thread zur Verarbeitung gereicht, ein wirkungsvolles Mittel, um Probleme mit der Nebenläufigkeit zu vermeiden. Eine Gruppe von Targets, die in demselben Thread registriert wurde, kann sich also bequem die Resourcen (Datenbanken, Dateien, Collections usw.) teilen, da sie niemals gleichzeitig darauf zugreifen.

    Für mehr Informationen über Targets siehe hier.

  • Namespaces

    Namespaces sind die nächstgrößere organisatorische Einheit. Sie sind vergleichbar mit Applikationen, und haben einen oder mehrere Threads. Targets werden in Namespaces registriert, und dabei einem bestimmten Thread zugewiesen.

    Auch Namespaces haben eine ID, die NamespaceID (NID).

    Für mehr Informationen über Namespaces siehe hier.

  • Kernel

    Der devel.one NODE besitzt einen Kernel mit einer Namespace-Registry. In dieser werden die Namespaces registriert.

    D1-NODES haben auch eine ID, die NODEID.

    Für mehr Informationen über den Kernel siehe hier.

Die Adresse eines Targets besteht aus Target-ID, Namespace-ID und NODE-ID. Das reicht, um jedes Target in einem devel.one-Netzwerk zu addressieren. Und damit steht auch nichts im Wege, die Targets quer über das Netzwerk zu verteilen. Die schriftliche Notation der Adresse lautet dann wie folgt: TID.NID.NODEID.

Targets implementieren Micro-Services, also Dienstleistungen für Applikationen. Davon kann es sehr viele geben, z.B. in einem Kfz-Navigationsgerät etliche Tausend. Dabei ist es nicht notwendig, das der Sender einer Message die genaue Adresse des Targets kennt, welches den Service anbietet. Services werden in Namespaces angemeldet. Man benötigt also eine Service-Adresse, an die man die Nachricht mit dem Request oder der Notifikation senden kann. Die Service-Adressen kann man über die Konfiguration variabel halten und auch zur Laufzeit wechseln. Mehr zu Services siehe hier.

Zur Nachrichtenverteilung benötigt man auch Observer und Observables, um Notifikationen bekannt zu machen. Auch hier können Services dienen, die per Observer überwacht werden können. Statt Listener (im herkömmlichen JAVA™ als Interface implementiert) funktionieren im devel.one-System Nachrichten, die von Services oder von einer zentralen Listener-Registry versandt werden. Die Verwaltung der Observer überläßt man am besten dem System, welches sich auch darum kümmert, sie abzubauen, wenn Targets abgemeldet werden. Über Services kann man also auch viele andere interessierte Targets erreichen.

devel.one unterstützt komplexe Targets mittels Zustandsmaschinen. Hierachical State Machines (HSM) bilden dabei die internen Zustände eines Targets ab und sorgen dafür, das z.B. nur Nachrichten verarbeitet werden, welche im aktuellen Zustand auch verarbeitet werden können. Nachrichten können abgelehnt werden, oder sie werden gespeichert, bis eine Aufgabe vollständig (modal) abgearbeitet wurde. Die Hierarchie hilft bei der Modellierung der Zustände nach UML.

Timer generieren einmalige oder wiederkehrende Nachrichten.

Mit Monitoren bekommt man Notifikationen auf die An- und Abmeldung von Targets und Services.