Wann ist es NICHT gut, Schauspieler in akka / erlang einzusetzen?


58

Ich arbeite jetzt täglich seit 7-8 Monaten mit akka. Als ich anfing, arbeitete ich an Anwendungen und bemerkte, dass Akteure im Prinzip irgendwo innerhalb des Aktorsystems für die Kommunikation zwischen den meisten Objekten verwendet wurden. Also habe ich das gleiche getan - einen anderen Schauspieler für x / y / z aufdrehen.

Es scheint mir, dass dies zu wahllos ist und die Komplexität dort erhöht, wo es nicht benötigt wird - aber ich kann keine Diskussionen darüber finden, wo Akteure gegen reine synchrone oder sogar asynchrone Logik über Futures eingesetzt werden sollten. Ich dachte über meine Haltung nach, nachdem mein Kollege etwas Ähnliches erwähnt hatte. In letzter Zeit habe ich mehrere Fälle erkannt, in denen ich über eine Aufgabe nachgedacht habe und es dann vermieden habe, einen anderen Akteur zu erstellen, weil ich in einer unveränderlichen Implementierung sicher das gleiche Ergebnis erzielen konnte - z. B. Konfigurationswerte von einer Datenbank oder einer Datei abrufen, auf die Sie nur sehr selten zugreifen Warten Sie, bis das Ergebnis der tatsächliche Anwendungsfall ist.

Insbesondere scheint es mir, dass in jedem Fall, in dem Sie mit unveränderlichen Zuständen spielen, Akteure Komplexität erzeugen und den Durchsatz begrenzen - eine reine Funktion in einem Objekt kann zum Beispiel gleichzeitig aufgerufen werden, ohne dass ein Risiko für eine Nebenläufigkeitsstufe besteht Ein Akteur kann jeweils nur eine Nachricht verarbeiten. Die andere Überlegung ist, dass Sie den Thread parken, wenn Sie auf das Ergebnis warten müssen, es sei denn, Sie beginnen mit der Verwendung von Futures. In Fällen, in denen Sie sich nicht um asynchrone Nachrichten oder Skalierung kümmern müssen, scheint es übertrieben zu sein, einen Schauspieler einzustellen.

Meine Frage ist also: Gibt es eine schlechte Zeit, um Schauspieler einzusetzen? Ich bin neugierig, wie erlang aussieht und würde gerne die Einsicht anderer Menschen haben. Oder ob es einige Prinzipien gibt, die sich mit der Verwendung von Schauspielern befassen.


Welche Art von Job bietet die Möglichkeit, monatelang täglich mit Akka zu arbeiten?
Den

3
Die guten. :) Oder nehmen Sie die Änderung selbst vor.
JasonG

Ich möchte genau wissen, was die Kompromisse zwischen askeinem Schauspieler und der Verwendung einer Ebene sind Future.
Max Heiber

2
Ich habe ein paar Jahre später ein Buch über Akka geschrieben und ich denke, Sie können es so zusammenfassen: Wenn Sie einen Zustand haben - zB einen Zähler -, stapfen mehrere Threads, die von / zu diesem Wert lesen und schreiben, aufeinander Ohne Synchronisation und Verriegelung. Wenn Sie diesen Status in einen Schauspieler einfügen, können Sie plötzlich sicher sein, dass auf ihn sicher zugegriffen wird, und Sie lassen keine Schreib- oder Lesezugriffe fallen. Schauspieler in Erlang und Akka gehen auch davon aus, dass der Zustand schlecht werden kann und der Schauspieler Fehler auslösen kann, sodass Sie einige Eigenschaften des Selbstheilungssystems haben. Futures sind einfacher, wenn Sie nicht mutieren müssen
JasonG

Viele Jahre später bin ich ein Erlang / Elixier-Programmierer und ich komme immer wieder mit neuen Einsichten darauf zurück :) Elixier ist ganz anders, da es keine Objekte als Alternative zu Prozessen gibt, sodass Prozesse immer dann erstellt werden, wenn Sie einen Status benötigen . Es ist einfach gleichzeitig. Dies ist immer noch die beste Heuristik.
JasonG

Antworten:


23

Dies ist eine Frage, die mich interessiert und an der ich einige Untersuchungen durchgeführt habe. Weitere Informationen finden Sie in diesem Blogbeitrag von Noel Walsh oder in dieser Frage zum Stapelüberlauf. Ich habe einige Meinungen, die ich anbieten möchte:

  • Ich denke, Akka, weil es mit Nachrichten funktioniert, fördert eine "Push-Denkweise". Aus Gründen der Parallelität würde ich oft argumentieren, dass dies nicht das ist, was Sie wollen. Ziehen ist viel sicherer. Beispielsweise besteht ein gängiges Muster für verteilte Systeme darin, dass eine Gruppe von Mitarbeitern Informationen in einer Warteschlange verarbeitet . Natürlich ist dies in Akka möglich, aber es scheint nicht unbedingt der erste Ansatz zu sein, den die Leute versuchen . Akka bietet auch dauerhafte Postfächer an, aber es hängt auch davon ab, wie Sie sie verwenden - eine einzelne gemeinsam genutzte Warteschlange ist viel flexibler als Warteschlangen pro Mitarbeiter zum Ausgleichen / erneuten Zuweisen von Arbeit.
  • Es ist ganz einfach, Ihre Klassen durch Schauspieler zu ersetzen. In der Tat scheinen einige Leute es sogar zu befürworten, indem sie sagen, Schauspieler sollten nur eine Sache tun . Aus logischer Sicht erhöht dies die Komplexität des Codes, wie Jason beschreibt, denn wenn jede Klasse ein Schauspieler ist, bedeutet dies eine Menge zusätzlicher Nachrichten und Empfangs- / Sendeblöcke. Außerdem wird es schwieriger, den Code zu verstehen und zu testen, da Sie die Formalität der Schnittstellen verlieren - und ich bin nicht davon überzeugt, dass Kommentare eine Lösung dafür sind . Auch trotz Akkas legendärer Effizienz bin ich der Meinung, dass die Verbreitung von Darstellern keine gute Idee ist - wenn wir Java-Threads verwenden, wissen wir, dass sie wertvoll sind und bewahren sie entsprechend auf.
  • Es hat etwas mit dem vorherigen Punkt zu tun, aber ein weiteres Ärgernis ist der Verlust von Typinformationen, die Noel und Pino hervorheben, da für viele von uns Scala statt anderer Sprachen wie Python verwendet wird. Es gibt einige Möglichkeiten, um dies zu umgehen, aber sie sind entweder nicht standardgemäß , nicht empfohlen oder experimentell .
  • Schließlich ist die Parallelität auch dann schwierig , wenn Sie die Einstellung "Absturz zulassen" haben . Alternative Programmiermodelle können helfen, aber sie lassen die Probleme nicht verschwinden - sie ändern sie - deshalb ist es gut, formal darüber nachzudenken . Joe Average-Entwickler greifen deshalb auch auf fertige Tools wie RabbitMQ-, Storm-, Hadoop-, Spark-, Kafka- oder NoSQL-Datenbanken zurück. Akka hat einige vorgefertigte Tools und Komponenten, was cool ist, aber es fühlt sich auch ziemlich niedrig an, so dass fertigere gemeinsame Elemente verteilter Systeme Entwicklern helfen und sicherstellen würden, dass Systeme richtig erstellt werden.

Wie Jason bin ich sehr gespannt auf die Einsichten anderer Leute. Wie kann ich einige der oben genannten Probleme lösen und Akka besser nutzen?


1
Ich fand diesen Beitrag über das Testen in Akka spot-on timgilbert.wordpress.com/2013/07/07/…
Mark Butler

"Komposition über Vererbung" ist immer noch nützlich für die Abhängigkeitsinjektion. Übergeben Sie die Abhängigkeit beispielsweise als Requisiten (verwendet Konstruktorparameter). Das Problem wäre dann die Überwachung - der erstellte Schauspieler würde an einer anderen Stelle als dem Schauspieler überwacht. Ein Router könnte verwendet werden, um eine Überwachungsstrategie um Akteure zu wickeln, die auf höchster Ebene erstellt wurden, aber heilig, das ist jetzt ziemlich komplex! Ich denke, Kuchen wäre eine bessere Lösung - haben Sie ein Merkmal mit der Schauspielererstellung für einen DB-Service-Schauspieler zum Beispiel. Dann verwenden Sie einfach ein Test-Mock / Stub-DB-Service-Merkmal im Textkontext.
JasonG

1
Ja, genau - Aufsicht funktioniert mit Abhängigkeitsinjektion nicht gut. Ich hatte auch Fälle, in denen es notwendig war, eine Fabrik anstelle der Klasse zu injizieren, ansonsten gab es merkwürdige Verschlussprobleme - ich schätze aufgrund von Akkas Behandlung von Fäden.
Mark Butler

Ich denke, das ist keine schlechte Idee - danke, vielleicht versuche ich sogar, ein bisschen darüber zu schreiben und Kontakte zu knüpfen. Sie könnten etwas injizieren, das die Requisiten vielleicht gibt? Eine Art Schauspielerfabrik, in der der Verbraucher den Schauspieler instanziieren kann. zB def method (arg) = return Props (new ActorWithArgs (arg)) von dieser (psuedo?) Factory, damit Sie den Akteur in den richtigen Kontext stellen können. Dies scheint eine gute Idee und ein gutes Ziel für Kuchenlösungen zu sein.
JasonG

Ich habe gerade mit diesem Kurs angefangen : coursera.org/course/posa Obwohl er sich in erster Linie an Personen richtet, die Android programmieren, bietet er auch einen guten Überblick über die Parallelität in Java. Eine Sache, über die ich mich wundere, ist "Ist Akka nicht nur eine ausgefallene Form von Event-Loops mit ein paar Schnickschnack (weil Sie Event-Loops auf verschiedene Threads setzen können)?".
Mark Butler

21

Es lohnt sich zu überlegen, wofür das Darstellermodell verwendet wird: das Darstellermodell

  1. ein Parallelitätsmodell
  2. das vermeidet den gleichzeitigen Zugriff auf den veränderlichen Zustand
  3. Verwenden von asynchronen Kommunikationsmechanismen zur Bereitstellung von Parallelität.

Dies ist hilfreich, da die Verwendung des gemeinsam genutzten Status mehrerer Threads sehr schwierig wird, insbesondere wenn Beziehungen zwischen verschiedenen Komponenten des gemeinsam genutzten Status bestehen, die synchronisiert bleiben müssen. Wenn Sie jedoch Domänenkomponenten haben, in denen:

  • Sie erlauben keine Parallelität, ODER
  • Sie erlauben keinen veränderlichen Zustand (wie bei der funktionalen Programmierung) ODER
  • Sie müssen sich auf einen synchronen Kommunikationsmechanismus verlassen,

dann wird das Schauspielermodell nicht viel (wenn überhaupt) Nutzen bringen.

Ich hoffe, das hilft.


Danke - ich denke, Sie müssen dann wirklich zwei Dinge bewerten - den veränderlichen Zustand und die Nebenläufigkeit? Kein Problem zu lösen, wenn eine Klasse zustandslos oder nicht gleichzeitig ist. Noch eine Überlegung - Ich denke, Fehlertoleranz ist ein weiterer Punkt? Beispiel: Wenn Sie einen unveränderlichen Redis-Client haben, der jedoch während der Ausführung fehlschlagen kann, ist dies kein guter Anwendungsfall. Dass ein Neustart dieses Schauspielers notwendig sein könnte? Da - obwohl die Klasse möglicherweise nur unveränderlich ist - es durchaus möglich ist, dass ein fehlerhafter Zustand außerhalb des unveränderlichen Akteurs vorliegt, der zum Fehlschlagen der Klasse führen kann.
JasonG

Ich denke, der Schauspieler, der für die Kommunikation mit redis verantwortlich ist, würde die Ausnahme bekommen und neu starten.
JasonG

@JasonG Meiner Meinung nach ist "Fehlertoleranz" kein Aspekt des Darstellermodells im Allgemeinen - es ist etwas, das mit der Implementierung des Darstellermodells in Erlang (und vielleicht Akka?) Einhergeht. Ich kann nicht mit redis sprechen, obwohl ich zugeben muss, dass "unveränderlicher Client" für mich seltsam klingt ... Wenn eine Softwarekomponente ausfallen kann, sehe ich nicht, wie sie als unveränderlich angesehen werden kann.
Aidan Cully

Fehlertoleranz und Überwachung gibt es in akka und es ist sehr ähnlich zu erlang. Ich verstehe, was Sie über unveränderlichen Client sagen, aber unveränderlich bedeutet, dass sich der Codestatus nirgendwo ändert. Wenn ich eine Verbindung beim Start initialisiere, ist es möglich, dass der Client-Code mit einer Neustart-Strategie, die bei jeder Art von Fehler angewendet wird, unveränderlich ist, indem der Akteur einfach neu initialisiert wird, wenn ein Problem auftritt.
JasonG

12

Ihre Intuition ist richtig, IMHO. Überall Schauspieler einzusetzen ist, als hätte man den sprichwörtlichen Hammer und sieht nur Nägel.

Die bewährte Methode von Erlang besteht darin, Prozesse / Akteure für alle Aktivitäten zu verwenden, die gleichzeitig stattfinden. Das heißt, genau wie im wirklichen Leben. Manchmal ist es schwierig, die richtige Granularität zu finden, aber meistens wissen Sie es nur, wenn Sie sich die modellierte Domäne ansehen und ein wenig gesunden Menschenverstand verwenden. Ich fürchte, ich habe keine bessere Methode, aber ich hoffe, es hilft.


Cool, danke. Ich bin wirklich gespannt, was in dieser Diskussion passiert.
JasonG

0

In der Reihenfolge Eingabe / Ausgabe von Nachrichten:

Ich habe kürzlich eine akka-basierte Anwendung kennengelernt, bei der das Actor-Modell tatsächlich Parallelitätsprobleme verursachte. Ein einfacheres Modell hätte unter Last besser gereicht.

Das Problem bestand darin, dass sich die eingehenden Nachrichten auf verschiedenen „Spuren“ bewegten (über verschiedene Akteurspfade), der Code jedoch davon ausging, dass die Nachrichten in der gleichen Reihenfolge an ihrem endgültigen Ziel ankamen, in der sie ankamen. Solange Daten mit ausreichend großen Intervallen eintrafen, funktionierte dies, da nur eine einzige widersprüchliche Nachricht zum Ziel raste. Als die Intervalle abnahmen, kamen sie nicht mehr in Ordnung und verursachten seltsames Verhalten.

Das Problem hätte mit ein bisschen weniger Schauspielern richtig gelöst werden können, aber es ist ein leichter Fehler, wenn man sie überbeansprucht.


Dies ist grundlegend und allgemein relevant. Sie können nur die Bestellung zwischen zwei Akteuren garantieren. doc.akka.io/docs/akka/current/scala/general/… Sie können die Lieferung von Bestellungen in keinem System garantieren, in dem Sie Fan-out / In betreiben . andreasohlund.net/2012/01/18/dont-assume-message-ordering
JasonG

-1

Meiner Meinung nach gibt es zwei Anwendungsfälle für Schauspieler. Gemeinsame Ressourcen wie Ports und dergleichen und großer Zustand. Der erste Punkt ist in der Diskussion bisher gut behandelt worden, aber der große Staat ist auch ein triftiger Grund.

Eine große Struktur, die mit jedem Prozeduraufruf übergeben wird, kann viel Stapel beanspruchen. Dieser Status kann in einen separaten Prozess gestellt, die Struktur durch eine Prozess-ID ersetzt und dieser Prozess nach Bedarf abgefragt werden.

Man kann sich Datenbanken wie Mnesia so vorstellen, dass sie den Status außerhalb des Abfrageprozesses speichern.


1
Könntest Du das erläutern? Meinst du großen Staat über das Netzwerk? Innerhalb eines lokalen Prozesses ist das Übergeben eines Verweises auf eine unveränderliche Struktur fast kostenlos, und Sie können keine veränderlichen Strukturen übergeben. Angenommen, Sie sprechen von einer großen veränderlichen Struktur, die zum Senden kopiert werden muss? Das ist also im Grunde wieder dasselbe - geteilter Zustand. Die Größe ändert eigentlich nichts. Lassen Sie mich wissen, wenn ich ein Missverständnis habe.
JasonG

Wie übergeben Sie einen Verweis? Sicherlich besteht der Weg dazu darin, die Struktur in einen Prozess zu setzen und die processid zu übergeben. Bei lokalen Aufrufen werden die Daten auf den Stapel gelegt und bei jedem rekursiven Aufruf erneut (mit Ausnahme der Endrekursion). Die rekursive Bearbeitung der Struktur kann über Listen erfolgen, um den Status von einem Aufruf auf den anderen zu übertragen. Dieser Status kann dann im anderen Prozess auf die Struktur verweisen.
Tony Wallace
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.