Aktorenmodell und Akka Teil 1/3

Heutzutage ist die Nachfrage nach äußerst skalierbaren, aber trotzdem zuverlässigen und fehlertoleranten Systemen so hoch wie nie.

Daher möchten wir im ersten Teil dieser dreiteiligen Serie eine Einführung in das Aktorenmodell geben. Im zweiten Teil der Serie wird es dann eine Einführung in das Aktorframework Akka geben. Akka ist im Übrigen eine Implementierung des Aktorenmodells auf Basis der JVM, welches mit begrenztem Aufwand das Verteilen einer Anwendung auf mehrere Systeme ermöglicht. Da es nur einen begrenzten Sinn hat, ein verteiltes System auf nur einer Maschine laufen zu lassen, wird der dritte Teil das Clustering mit Akka behandeln.

Das Aktorenmodell

Das Aktorenmodell wurde erstmals 1973 in einem Paper von Carl Hewitt, Peter Bishop und Richard Steiger vorgestellt. In diesem Video wird es außerdem von Carl Hewitt selbst vorgestellt und detailliert erläutert. Der wichtigste Grundbegriff des Aktorenmodells ist der Aktor. Ein Aktor ist eine gekapselte Einheit in einem Programm, vergleichbar mit einem Objekt in einer objektorientierten Programmiersprache. Mehrere dieser Aktoren können über den Austausch von Nachrichten kommunizieren. Damit stellt das Modell eine Alternative zum (a)synchronen Austausch von Information über gemeinsame Speicherbereiche (shared memory) dar. Die Kosten bestehen in erster Linie aus einem etwas höhereren Overhead. Der Versand von Nachrichten ist schließlich komplexer, als in gemeinsamen Speicher zu schreiben und zu lesen, beziehungsweise eine Funktion im lokalen Speicher aufzurufen. Ein weiteres eher negatives Merkmal des Aktorenmodells ist, dass Informationen im gleichen System redundant vorhanden sein können (nämlich beim Absender und beim Empfänger der Information).

Dafür fällt das Problem der Speichersynchronisierung bei der Verwendung mehrerer Maschinen weg, und die Anwendung lässt sich theoretisch effizienter über mehrere Maschinen skalieren. Außerdem entsteht durch die strengere Kapselung ein höherer Basissicherheitsstandard, als bei Anwendungen, die gemeinsamen Speicher verwenden.

Was ist ein Aktor?

Ein Aktor ist, wie oben genannt, eine gekapselte Einheit in einem Programm. Ein Aktor besitzt die folgenden drei abstrakten Eigenschaften:

  • Er kann neue Aktoren erstellen.
  • Er kann über Nachrichten asynchron mit anderen Aktoren kommunizieren.
  • Er kann festlegen, was mit der nächsten Nachricht geschieht. Dies impliziert, dass ein Aktor einen internen Status besitzt und diesen verändern kann. Er kann also empfangene Nachrichten verarbeiten und Resultate speichern.

Ein Programm nach dem Aktorenmodell ist ein System, welches aus mehreren solcher Aktoren besteht. Der Grundgedanke dabei ist, dass die Aktoren theoretisch beliebig auf einem Cluster aus mehreren Maschinen verteilt werden können, da es durch das ständige Messaging keine Methodenaufrufe gibt, für die das aufrufende und das aufgerufene Objekt logischerweise beide lokal vorhanden sein müssten (Bei Methodenaufrufen über RPC müssen die Objekte zwar ebenfalls nicht beide auf einer Maschine sein, aber RPC läuft im Endeffekt auch über Nachrichten und nicht über direkte Speicheraufrufe).

Addressierung

Das Aktorenmodell sieht außerdem vor, dass die Aktoren mit einer Relation von m:n adressierbar sein sollen. Das bedeutet, dass ein Aktor trivial repliziert werden und über die gleiche Adresse, wie das Original angesprochen werden kann. Außerdem können mehrere Adressen auf die gleiche Instanz eines Aktors zeigen.

Alle Nachrichten werden asynchron verschickt. Wenn nun eine Nachricht an eine Adresse geschickt wird, hat der Absender keine Möglichkeit festzustellen, ob hinter der Adresse einer oder mehrere Empfänger stehen. Außerdem kann er nicht feststellen, an welchen oder an wie viele Empfänger die Nachricht letztendlich ausgeliefert wurde. Die konkreten Instanzen der Aktoren werden ja wie oben genannt durch die Adresse abstrahiert (siehe Abbildung „Adressierung“).

Aktorenmodell - Addressierung

Wie dieses Adresssystem im Detail funktioniert und die Aktoren eindeutig identifiziert, liegt bei der jeweiligen Implementierung des Aktorenmodells.

Parallelisierbarkeit und Nebenläufigkeit

Nachdem die Nachrichten also bei einem Aktor eintreffen, werden sie in eine Warteschlange eingefügt, welche nach dem First-In-First-Out (FiFo) Prinzip abgearbeitet wird. Der gesamte Aktor an sich arbeitet ausschließlich sequenziell. Nebenläufigkeit und Parallelisierbarkeit wird über die Kombination mehrerer Aktoren oder Instanzen des gleichen Aktors erreicht. Außerdem kann ein Aktor selbst neue Aktoren erstellen und die Abarbeitung einer Aufgabe über diesen Weg parallelisieren (siehe Abbildung „Parallelisierung“) oder nebenläufig Subaufgaben lösen.

Aktorenmodell - Parallelisierung

Der Nachrichtenversand an sich läuft üblicherweise mit dem Quality Of Service (QoS) Level „at most once“ ab, das heißt, es können Nachrichten verloren gehen, aber es gibt keine Duplikate. Außerdem müssen die Nachrichten nicht in der gleichen Reihenfolge beim Empfänger in der Queue eintreffen, wie sie vom Absender geschickt wurden. Um beispielsweise ein QoS Level von „exactly once“ (erläutert im Apache ActiveMQ Artikel Teil 1), oder eine totale Ordnung der Nachrichten zu garantieren, können allerdings weitere Aktoren (Metaaktoren) verwendet werden.

Kontrollaktoren

Insbesondere zur Erhöhung der Fehlertoleranz und Robustheit eines aus Aktoren bestehenden Systems können derartige Metaaktoren verwendet werden. Diese Metaaktoren sind insbesondere dann relevant, wenn ein Aktor nach dem Prinzip „let it crash“ arbeitet. Das bedeutet, dass der Aktor bei einer fehlerhaften oder nicht spezifizierten Eingabe abstürzt, anstatt eine Fehlermeldung zurückzugeben. Viele Aktorsysteme arbeiten nach diesem Prinzip, da es aus Performancegründen häufig sinnvoller ist, den Aktor bei Problemen einfach neu zu starten, als sämtliche Fehlerfälle abzufangen und korrekt zu behandeln. Damit diese Abstürze nicht die Stabilität des ganzen Systems gefährden, wird ein anderer Aktor als Kontrollaktor eingesetzt und kann den potenziell instabilen Aktor nach einem etwaigen Absturz wiederherstellen (siehe Abbildung „Kontrollaktor“).

Aktorenmodell - Kontrollaktor

Um Aktorensysteme zu entwickeln, wurde zunächst die Programmiersprache Erlang entwickelt. Sie ist mit dem Ziel, Aktorensysteme damit zu entwickeln, designt worden. Außerdem gibt es Celluloid für Ruby und Akka für die JVM. Wir werden uns Akka im nächsten Artikel dieser Serie genauer ansehen.

Short URL for this post: https://wp.me/p4nxik-2NO
This entry was posted in Java Runtimes - VM, Appserver & Cloud and tagged , , , , , , . Bookmark the permalink.

One Response to Aktorenmodell und Akka Teil 1/3

  1. Pingback: Aktorenmodell und Akka – Teil 2/3 | techscouting through the java news

Leave a Reply