Open Source Java Projekte: Akka

Das Akteurmodell ist ein Paradigma für die Nachrichtenübermittlung, das einige der größten Herausforderungen beim Schreiben von gleichzeitig skalierbarem Code für heutige verteilte Systeme löst. In dieser Folge von Open Source Java-Projekten stellt Steven Haines Akka vor, ein JVM-basiertes Toolkit und eine Laufzeit, die das Akteurmodell implementieren. Beginnen Sie mit einem einfachen Programm, das zeigt, wie ein Akka-Nachrichtenübermittlungssystem miteinander verbunden ist, und erstellen Sie dann ein komplexeres Programm, das gleichzeitige Prozesse zur Berechnung von Primzahlen verwendet.

Wenn Sie Erfahrung mit traditioneller Parallelitätsprogrammierung haben, werden Sie vielleicht das Akteurmodell zu schätzen wissen, ein Entwurfsmuster zum Schreiben von gleichzeitigem und skalierbarem Code, der auf verteilten Systemen ausgeführt wird. Kurz gesagt, so funktioniert das Schauspielermodell:

  1. Anstatt ein Objekt direkt aufzurufen, erstellen Sie eine Nachricht und senden sie über eine Akteurreferenz an das Objekt (als Akteur bezeichnet ).
  2. Die Akteurreferenz speichert die Nachricht in einem Postfach.
  3. Wenn ein Thread verfügbar wird, sendet die Engine, auf der der Akteur ausgeführt wird, diese Nachricht an sein Zielobjekt.
  4. Wenn der Akteur seine Aufgabe erledigt hat, sendet er eine Nachricht an das Ursprungsobjekt zurück, das auch als Akteur betrachtet wird.

Sie könnten den Verdacht haben, dass das Akteurmodell eher eine ereignisgesteuerte oder Nachrichtenübermittlungsarchitektur als eine strikte Parallelitätslösung ist, und Sie hätten Recht. Aber Akka ist eine andere Geschichte: Eine Implementierung eines Akteurmodells, mit der Entwickler eine beeindruckend hohe Parallelität bei sehr geringem Overhead erzielen können.

Laden Sie den Quellcode für diesen Artikel herunter. Erstellt von Steven Haines für JavaWorld.

Parallelität mit Akka (und Scala) neu denken

Akteure bieten eine einfache Abstraktion auf hoher Ebene für Parallelität und Parallelität. Sie unterstützen asynchrone, nicht blockierende und ereignisgesteuerte Hochleistungsprogrammierung und sind einfache Prozesse. (Akkas Gründungsunternehmen Typesafe behauptet, bis zu 2,7 Millionen Akteure pro Gigabyte RAM zu haben.) Akka und andere Frameworks für die Nachrichtenübermittlung bieten eine Problemumgehung für die Herausforderungen der Multithread-Programmierung (siehe die Seitenleiste "Was ist falsch an der Multithread-Programmierung?") Erfüllung einiger der aufkommenden Anforderungen der Unternehmensprogrammierung:

  • Fehlertoleranz : Supervisor-Hierarchien unterstützen eine "Let-it-Crash" -Semantik und können in einer wirklich fehlertoleranten Bereitstellung über mehrere JVMs ausgeführt werden. Akka eignet sich hervorragend für hoch fehlertolerante Systeme, die sich selbst heilen und die Verarbeitung nie beenden.
  • Standorttransparenz : Akka kann in einer verteilten Umgebung mit einer reinen asynchronen Strategie zur Nachrichtenübermittlung ausgeführt werden.
  • Transaktoren : Kombinieren Sie Akteure mit Software Transaction Memory (STM), um Transaktionsakteure zu bilden, die atomare Nachrichtenflüsse und automatische Wiederholungs- und Rollback-Funktionen ermöglichen.

Da das Darstellermodell für die meisten Java-Entwickler relativ neu ist, werde ich zunächst erklären, wie es funktioniert, und dann untersuchen, wie es in Akka implementiert ist. Schließlich werden wir das Akka-Toolkit in einem Programm ausprobieren, das Primzahlen berechnet.

Was ist falsch an Multithread-Programmierung?

Multithread-Programmierung bedeutet im Grunde, mehrere Kopien Ihres Anwendungscodes in ihren eigenen Threads auszuführen und dann den Zugriff auf freigegebene Objekte zu synchronisieren. Während es sich um ein komplexes Problem handelt, weist die Multithread-Programmierung drei Hauptfehlerlinien auf:

  • Freigegebene Objekte : Wenn mehrere Threads auf gemeinsam genutzte Objekte zugreifen, besteht immer die Gefahr, dass ein Thread die Daten ändert, mit denen ein anderer Thread darunter arbeitet. In der Regel lösen Entwickler dieses Problem, indem sie die abhängige Funktionalität in eine synchronisierte Methode oder einen synchronisierten Codeblock einkapseln. Möglicherweise versuchen zahlreiche Threads, diesen Codeblock einzugeben, aber nur ein Thread wird durchkommen. Die anderen warten, bis der Vorgang abgeschlossen ist. Dieser Ansatz schützt Ihre Daten, erstellt jedoch auch einen Punkt in Ihrem Code, an dem Vorgänge seriell ausgeführt werden.
  • Deadlock : Da wir den Zugriff auf Code synchronisieren müssen, der auf gemeinsam genutzten Ressourcen ausgeführt wird, tritt manchmal ein Deadlock auf. Bei der Codesynchronisation (wie oben beschrieben) erhält der erste Thread, der in einen synchronisierten Block eintritt, die Sperre, die dem Objekt gehört, für das die Operation synchronisiert wird. Bis diese Sperre aufgehoben ist, darf kein anderer Thread diesen Codeblock eingeben. Wenn Thread 1 die Sperre für synchronisierten Block 1 erhält und Thread 2 die Sperre für synchronisierten Block 2 erhält, Thread 1 jedoch Zugriff auf synchronisierten Block 2 und Thread 2 Zugriff auf synchronisierten Block 1 benötigt, werden die beiden Threads niemals abgeschlossen und sollen festgefahren sein .
  • Skalierbarkeit : Das Verwalten mehrerer Threads in einer einzelnen JVM ist schwierig genug, aber wenn Sie die Anwendung über mehrere JVMs skalieren müssen, steigt das Problem um eine Größenordnung. Wenn Sie gleichzeitig Code über mehrere JVMs ausführen, müssen Sie in der Regel den gemeinsam genutzten Status in einer Datenbank speichern und sich dann auf die Datenbank verlassen, um den gleichzeitigen Zugriff auf diese Daten zu verwalten.

Akka und das Schauspielermodell

Akka ist ein Open Source Toolkit und eine Laufzeit, die auf der JVM ausgeführt werden. Es ist in Scala geschrieben (eine Sprache, die oft für Parallelität angepriesen wird), aber Sie können Java-Code (oder Scala) verwenden, um alle seine Bibliotheken und Funktionen aufzurufen.

Das Hauptentwurfsmuster, das Akka implementiert, ist das Akteurmodell, wie in Abbildung 1 dargestellt.