Aktor-basierter Entwurf

Aktoren bieten ein Konzept, um Architekturen im Enterprise zu strukturieren. Unterstützung dafür bieten Akka, Erlang und weitere Plattformen. Das Aktor-Modell lässt sich sehr gut für den konzeptionellen Entwurf verteilter Systeme nutzen, aber auch für die technische Realisierung in speziellen Aktor-Laufzeitsystemen.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 4 Min.
Von
  • Dr. Michael Stal

Aktoren bieten ein Konzept, um Architekturen im Enterprise zu strukturieren. Unterstützung dafür bieten Akka, Erlang und weitere Plattformen. Das Aktor-Modell lässt sich sehr gut für den konzeptionellen Entwurf verteilter Systeme nutzen, aber auch für die technische Realisierung in speziellen Aktor-Laufzeitsystemen.

Heutzutage ist es en vogue, zu jeder passenden oder unpassenden Gelegenheit Microservices als Lösung zu präsentieren. Es gibt mit Aktoren allerdings schon ein wesentlich älteres Konzept mit ähnlichem Potenzial. Hier möchte ich das Konzept vorstellen, weil es sich aus meiner Sicht auch gut zum Modellieren verteilter Anwendungen eignet. 

Statt langer Grundlageneinführung mache ich es kurz. Aktoren unterliegen folgenden Regeln:

  • Ein Aktor hat genau eine klar umrissene Verantwortlichkeit und einen stark begrenzten Scope.
  • Ein Aktor ist ein aktives Objekt mit mindestens einem dedizierten Worker-Thread.
  • Aktoren können keine gemeinsamen logischen Threads besitzen.
  • Der Zustand eines Aktors ist von außen weder sichtbar noch zugreifbar.
  • Ein Aktor besitzt eine Nachrichtenwarteschlange.
  • Andere Peers können ausschließlich über Nachrichten mit einem Aktor kommunizieren.
  • Nachrichten dürfen nur Werte enthalten, um Seiteneffekte zu vermeiden.
  • Eine Referenz auf einen Aktor gilt als Wert.
  • Ein Aktor hat eine eindeutige Identität.
  • Aktoren können wie ein Service zustandslos arbeiten, aber auch zustandsbehaftet agieren.
  • Aktoren können eine Gruppe mit gemeinsamer Identität bilden, die nach außen als virtueller Aktor agiert. Jedes Mitglied ist ein Replikat mit gemeinsamem Gruppenzustand.
  • Aktoren können an Transaktionen mitwirken.

Ein Aktor agiert als aktives Objekt und kommuniziert über Nachrichten mit seinen Peers

Eine aktorbasierte Anwendung besteht somit als asynchronen, miteinander kooperierenden Aktoren. Ein initialer Hauptaktor oder ein nicht als Aktor ausgelegter Peer initiiert und orchestriert dabei alle Systemaktivitäten beziehungsweise die Systemabläufe (Workflows). Im Gegensatz zu Services im konventionellen Sinn sind Aktoren keine passiven Objekte.

Mit dem Aktoransatz lassen sich folglich nicht nur Microservice-Architekturen realisieren, sondern auch exotischere Anwendungen wie zum Beispiel intelligente Schwärme mit emergenten Verhaltensmustern. Dinge oder Knoten im Internet lassen sich ebenfalls als Aktoren betrachten. Der Reiz dieses Modells besteht also darin, dass es transparent bleibt, ob sich unter der Haube eines Aktors Software oder Hardware verbirgt.

Ein Aktor besitzt nach außen eine Schutzhülle, kann aber seinerseits auf seine Umgebung beziehungsweise auf Ressourcen zugreifen.

Um optional den Lebenszyklus eines Aktors verwalten zu können, braucht es ein Laufzeitsystem, das über Schnittstellen mit Aktoren interagiert und ihnen über einheitliche APIs Funktionalität anbietet. Letzteres soll verhindern, dass Aktoren zu stark von der zugrundeliegenden Umgebung abhängig sind. Die angebotenen Funktionen liefern grundlegende Dienste, etwa zum Zugriff aus Ressourcen, zur Suche nach anderen Aktoren, zur Kommunikation mit der Außenwelt, zum persistenten Abspeichern/Laden von Daten, zur Erzeugung neuer Aktoren u.v.a.m. Die benötigten Referenzen auf APIs kann das Laufzeitsystem dem Aktor per Dependency Injection "einflößen". 

Das Laufzeitsystem ist wohlgemerkt ein optionales Add-on und als solches für die Steuerung des Lebenszyklus von Aktoren verantwortlich. Es kann über eine interne Aktorschnittstelle Änderungen des Lebenszyklus an die betroffenen Aktoren melden. Ein Aktor lässt sich daher auch als Zustandsmaschine betrachten.

Typische Zustände könnten etwa folgende sein:

  • NON-EXISTING
  • CREATED
  • INITIALIZED
  • RUNNING
  • PAUSED
  • IN-NEW-TRANSACTION
  • IN-TRANSACTION-COMMIT
  • IN-TRANSACTION-ROLLBACK
  • PRE-DELETION
  • DELETED

Wie gesagt, ein derart weitreichendes Laufzeitsystem ist optional und eher beim lokalen Auftreten sehr vieler eher feingranularer Aktoren notwendig, wie sie in der Regel bei Mikroservice-Architekturen vorkommen.

Damit an dieser Stelle keine Missverständnisse auftreten: Ein Laufzeitsystem kann ein leichtgewichtiges Framework wie Spring sein, aber auch ein extra dafür ausgelegter und schwergewichtiger Docker-Container bzw. ein Betriebssystem.

Genau genommen fußen also SOA-Systeme und Mikroservices-Ansätze auf dem aktorbasierten Paradigma, das aber noch einen Schritt weitergeht, indem es auch aktive Objekte erlaubt. Aktoren eignen sich daher auch zur Modellierung für intelligente bzw. emergente Systeme. 

Der Begriff "Modellieren" soll in diesem Fall bedeuten, dass sich das architektonische Aktor-Paradigma auch von der technischen Realisierung trennen lässt. Aktoren bieten in jedem Fall ein gutes Denkmodell beziehungsweise eine gute Metapher, selbst wenn die technische Realisierung auf keinem Autor-Laufzeitsystem basiert.

()