2017-11-19 4 views
2

Also ich erst vor kurzem akka außerhalb einer Spielzeug-Kapazität, und ich kann nicht helfen zu bemerken, dass es und OTP dynamischen Typisierung teilen trotz scala die allgemeine Vorliebe für statische Typen. Ich fing an, ein wenig herum zu graben und stieß auf this Wadler paper, die ein HM-System über erlang Interprozesskommunikation beschreibt. Nichtsdestotrotz bezieht sich an answer to this question from SO auf Wadlers und Marlows Versagen, die skizzierte Skizze der Kommunikation vom Prozesstyp zu liefern. Als Referenz bin ich meistens in Code wie folgt enttäuscht:Gibt es etwas Unmögliches an statisch schreibenden Akteurmodellen der Interprozesskommunikation?

def receive = { 
    case "test" => log.info("received test") 
    case _ => log.info("received unknown message") 
    } 

Ich weiß, dass in der Praxis Dialysator vielen Nutzen eines echten Typ-Systems zur Verfügung stellen kann, aber warum genau ist es so schwierig, statisch verifizierte Akteursysteme erstellen? Ist es nur, dass wir dazu neigen, Future oder Observable/Iteratee Bibliotheken oder Channel -modeled IO anstelle von Aktorsystemen zu schreiben, wenn wir Typsysteme verwenden, oder gibt es eine technische Schwierigkeit, die Wadler und Marlow verpasst haben?

Antwort

5

Die Art der Sicherheit in die Welt der Akka-Schauspieler zu bringen, ist seit Jahren ein Thema. Die aktuelle Manifestation dieser laufenden Bemühungen ist die Akka Typed API, die Änderungen unterliegt.

Neben der verlinkten Dokumentation gibt eine spannende Diskussion über die Akka User List von vor ein paar Jahren (Titel: "Wie kann ich untypisierte Akteure mit typgerechter Programmierung versöhnen?") Weitere Einblicke in typisierte Akteure. Lesen Sie die ganze Diskussion here für den gesamten Kontext, aber unten sind einige Auszüge:


Von Derek Wyatt:

Was Sie erleben, ist ein Trade-off. Schauspieler bieten einen Trade-off, den Sie nicht zu berücksichtigen scheinen; Endpunkte (Actors) sind nicht typisiert und die Nachrichten, die sie behandeln, sind stark typisiert.

Sie können nicht einen Actor in der Lage sein, "irgendetwas" mit einer typspezifischen Empfangsmethode zu verarbeiten. Bei der Actor-Programmierung sollte es mir möglich sein, so viele Vermittler wie möglich in den Nachrichtenfluss einzufügen und die beiden Endpunkte nicht zu stören. Die Intermediäre sollten ebenfalls nicht wissen, was gerade passiert (Load Balancer, Router, Logger, Cacher, Mediatoren, Scatter-Gather und so weiter). Sie sollten sie auch um einen Cluster herum verschieben können, ohne die Endpunkte zu stören. Sie können auch eine dynamische Delegation in einem Actor einrichten, ohne dass Sie wirklich verstehen müssen, was vor sich geht - zum Beispiel ein Actor, der den "Hauptdialekt" spricht, aber an etwas anderes delegiert, wenn er nicht versteht, was gesagt wird.

Wenn Sie alle diese Funktionen eliminieren möchten, können Sie den gesuchten Typesicherheitsdeterminismus erhalten (solange Sie in denselben JVM-übergreifenden JVMs bleiben, wird ein "what the Hölle, ich rede wirklich mit? "Frage, die eine Kompilierzeit Versicherung beseitigt ....

Kurz gesagt, Sie aufgeben Typ Sicherheit, um die Tür zu einer ganz neuen Reihe von Einrichtungen zu öffnen. Willst du nicht die Typ-Sicherheit verlieren?Schließen Sie die Tür :)


Von Endre Varga:

Das Problem ist, dass Typ-Systeme für die lokalen und nicht verteilt Berechnungen ausgelegt sind. Schauen wir uns ein Beispiel an.

einen Schauspieler vor, das drei Zustände, A, B und C hat

  • im Zustand A er Nachrichten vom Typ X akzeptiert, und wenn eines empfängt, geht es
  • Im Zustand B B Es akzeptiert Nachrichten vom Typ X und Y. wenn X empfangen werden, geht in C, wenn Y, dann in B bleibt
  • im Zustand C akzeptiert es Nachrichten vom Typ Z

Nun zu einem Schauspieler Sie von dem Zustand ausgehend senden A eine Nachricht X. Zwei Dinge können passieren:

  • X geliefert wird, so sind die möglichen akzeptierten Typen sind {X, Y}
  • X verloren, so die akzeptierte Art ist {X}

Der Durchschnitt derjenigen ist {X}.

Nun stell dir vor, dass Sie eine andere Nachricht X. Drei Dinge senden passieren kann:

  • beide X geliefert wurden, so die akzeptierte Typ {Z}
  • nur eines der X geliefert wurden, die andere die akzeptierten Typen sind {X, Y}
  • beide X verloren wurden, ist die akzeptierte Art {X}

der Schnittpunkt der oben genannten Fälle ist die leere Menge ist verloren, so.

Also was sollte die lokale Typ-Darstellung eines Akteurs sein, dass Sie zwei Nachrichten vom Typ X gesendet haben?

Lassen Sie uns das Beispiel ändern und annehmen, dass es keinen Nachrichtenverlust gab, aber nehmen wir den Standpunkt eines anderen Absenders. Dieser Absender weiß, dass vom anderen Absender zwei X an unseren Beispiel-Akteur gesendet wurden. Welche Nachrichten können wir senden? Es gibt drei Szenarien:

  • sowohl der X durch die anderen Sender gesendet bereits angekommen ist, so der akzeptierte Typ {Z}
  • nur die erste X durch die anderen Sender gesendet noch gekommen ist, so die akzeptierten Typen ist {X, Y}
  • kein X noch angekommen ist, wird angenommen Typ {X}

der Schnittpunkt der obigen Fälle die leere Menge ist.

Wie Sie sehen, ohne eine Antwort von einem Schauspieler zu erhalten, ist der beweisbare Typ eines Schauspielers normalerweise nichts oder etwas nutzloses.Nur Antworten können den möglichen Typ eines Schauspielers vermitteln, und selbst das kann nicht garantiert werden, wenn es gleichzeitige Absender gibt.


Von Dr. Roland Kuhn:

Ich bin froh, dass Sie diese Diskussion bringen, mein Wunsch, ein gewisses Maß an statische Typisierung zu Akka hinzuzufügen, ist so alt wie mein Beteiligung am Projekt. Wenn Sie in die 1.x Vergangenheit schauen, werden Sie akka.actor.Channel [T] finden, das in diesem Sinne konzipiert wurde, und in 2.1 und 2.2 gab es Typed Channels als ein makrobasiertes Experiment. Letzteres hat tatsächlich die Grenze vom Gedankenexperiment zum Code überschritten, und Sie können es gerne ausprobieren, um ein Gefühl dafür zu bekommen, wie statische Typen mit einem sehr dynamischen System interagieren.

Der Hauptmangel von Typed Channels war seine unangemessene Komplexität (zu viele Typparameter und zu komplexe Typen - mit Typenlisten und Maps - in ihnen). Wir nähern uns allmählich einem Entwurf, der das richtige Gleichgewicht finden könnte, aber im Wesentlichen bedeutet es, dass wir Akka-Akteure entfernen (was auch andere sehr willkommene Vorteile hat, wenn es darum geht, Dinge in zukünftigen Transformationen zu schließen). Der Kern davon ist es, ActorRef [T] mit der Art von Nachricht zu parametrisieren, die er akzeptiert (mit den offensichtlichen Folgewirkungen auf Props [T], Actor [T] und so weiter). Dann kann ein Actor Verweise auf sich selbst mit dem entsprechenden Typ offen legen und sie an andere Akteure senden - in bestimmten Nachrichten, um Typ-Löschung zu umgehen. Dies würde sogar die Formulierung von Nachrichtenprotokollen, a.k.a. Sitzungstypen oder zumindest nahe daran ermöglichen.

Derek machte einen ausgezeichneten Punkt darüber, wie das Aktormodell wirklich davon profitiert, dass es von Typen nicht eingeschränkt wird: Ein Nachrichtenrouter muss nicht notwendigerweise etwas über die Nachrichten wissen, die ihn durchlaufen. Wie gut es funktioniert, den Router selbst zu parametrisieren, bleibt abzuwarten, aber in der Regel werden solche Routinestufen die Typinformationen zerstören, da können wir nicht viel tun. Ihr Argument, dass eine Typ-Überprüfung besser ist als gar keine, ist eine, die bei mir gut ankommt, solange der Unterschied für den Entwickler wirklich offensichtlich ist: Wir müssen ein falsches Gefühl der Sicherheit vermeiden.

Das bringt mich zu Endre's gültiger Interjektion, dass konkurrierendes Verhalten für statische Verifizierung nicht zugänglich ist. Das Problem ist viel umfassender als der Verlust von Nachrichten, da jede nichtdeterministische Aktion zu einer Typ-Disjunktion führen müsste, die unsere schönen statischen Typen durch exponentielle Explosion der Typstruktur zerstört. Das bedeutet, dass wir Typen, die deterministisch sind, nur praktisch ausdrücken können: Wenn Sie eine Nachricht vom Typ A an einen Akteur senden, erhalten Sie möglicherweise eine Nachricht vom Typ B (was bedeutet, dass Sie einen ActorRef [B] liefern müssen). innerhalb der A-Nachricht), wobei A und B typischerweise Summentypen sind wie "alle von diesem Akteur akzeptierten Befehle" und "alle Antworten, die möglicherweise gesendet werden können". Es ist unmöglich, qualitative Zustandsänderungen eines Akteurs zu modellieren, da der Compiler nicht wissen kann, ob sie tatsächlich auftreten werden oder nicht.

Es gibt jedoch etwas Licht: Wenn Sie Nachricht B erhalten, die ein ActorRef [C] vom Ziel enthält, dann haben Sie Beweise, dass die Wirkung von Nachricht A aufgetreten ist, so dass Sie jetzt davon ausgehen können, dass der Akteur ist in einem Zustand, in dem sie Nachricht C akzeptiert. Aber das ist keine Garantie, der Schauspieler könnte in der Zwischenzeit abgestürzt sein.

Beachten Sie, wie dies nicht von Remotemessaging abhängt. Ihr Wunsch, Schauspieler in einen Nebenläufigkeits- und einen Distributionsteil zu spalten, ist sehr verständlich, ich dachte dasselbe. Dann wurde mir klar, dass Nebenläufigkeit und Verteilung eigentlich das Gleiche sind: Prozesse können nur dann gleichzeitig ablaufen, wenn ihre Ausführung räumlich oder zeitlich getrennt ist, also verteilt ist, und umgekehrt die endliche Lichtgeschwindigkeit jene verteilten Prozesse impliziert wird per Definition gleichzeitig sein.Wir wollen Verkapselung und Kompartimentierung für unsere Akteure, kommunizieren nur mit Nachrichten, und dieses Modell bedeutet, dass zwei Akteure immer voneinander getrennt sind, auch wenn sie auf der gleichen JVM laufen (Warteschlangen können voll laufen, Fehler können auftreten, Kommunikation) ist nicht absolut zuverlässig - obwohl seine Zuverlässigkeit deutlich höher ist als im Netzwerkfall. Wenn Sie an moderne Prozessoren denken, sind die verschiedenen Kerne und vor allem die Steckdosen auch durch Netzwerke getrennt, sie sind nur viel schneller als das Gigabit-Ethernet Ihres Großvaters.

Genau deshalb glaube ich, dass das Actor Modell genau die richtige Abstraktion für die Modellierung unabhängiger Stücke in Ihren Anwendungen jetzt und in der Zukunft ist, da die Hardware selbst immer mehr verteilt wird und die Akteure nur die Essenz erfassen . Und wie ich oben argumentiert habe, sehe ich Raum für Verbesserungen auf der Seite der statischen Typisierung.

+0

Ich finde Vargas Erklärung die zwingendste, aber die ganze Diskussion ist sehr hilfreich; Vielen Dank – jcc333

Verwandte Themen