Ich habe die folgende Anforderung
Im Moment habe ich einen einzigen Akteur, der alle oben genannten Aufgaben wie folgt ausführt:
%Vor%Die Operation readFile enthält verschiedene Teilaufgaben, von denen ich denke, dass sie ein separater Akteur sein sollte. Aber da die Rückgabe der Operation readFile () für den Akteur erforderlich ist, um seine Hauptaufgabe des Sendens der Anforderung auszuführen, könnte dies eine Blockierung sein, die laut den Dokumenten nicht empfohlen wird. Was ist der beste Weg, dies zu tun? Futures?
Offizielle Dokumentation bietet folgende Lösungen:
- Machen Sie den blockierenden Aufruf innerhalb eines Akteurs (oder einer Gruppe von Akteuren, die von einem Router verwaltet werden [Java, Scala]) und stellen Sie sicher, dass Sie einen Thread-Pool konfigurieren, der entweder für diesen Zweck bestimmt ist oder eine ausreichende Größe hat.
- Führen Sie den blockierenden Anruf innerhalb einer Zukunft durch und stellen Sie eine Obergrenze für die Anzahl solcher Anrufe zu einem beliebigen Zeitpunkt sicher (das Senden einer unbegrenzten Anzahl von Aufgaben dieser Art wird Ihre Speicher- oder Thread-Limits erschöpfen).
- Führen Sie den blockierenden Aufruf innerhalb einer Future aus und stellen Sie einen Threadpool mit einer Obergrenze für die Anzahl der Threads bereit, die für die Hardware geeignet ist, auf der die Anwendung ausgeführt wird.
- Widmen Sie einen einzelnen Thread, um eine Gruppe von blockierenden Ressourcen zu verwalten (z. B. einen NIO-Selektor, der mehrere Kanäle antreibt), und leiten Sie Ereignisse weiter, wenn sie als Nachrichten für Akteure auftreten.
Die Verwendung der Futures gehört zu den offiziell vorgeschlagenen Ansätzen, jedoch mit besonderer Vorsicht.
Betrachten wir den ersten Ansatz, weil IMO konsistenter ist.
Extrahieren Sie zunächst alle blockierenden IO-Operationen in neue Aktoren, die nur eine blockierende IO-Operation durchführen. Angenommen, es gibt nur eine solche Operation für die Kürze:
%Vor% Fügen Sie Konfiguration für den Dispatcher hinzu, die sich um die Blockierung von Akteuren kümmert, in Actor-Systemkonfigurationsdatei (normalerweise application.conf
):
Bitte stellen Sie sicher, dass Sie die Konfigurationsdatei beim Erstellen des Actor-Systems verwenden (insbesondere, wenn Sie sich entschieden haben, einen nicht standardmäßigen Dateinamen für die Konfiguration zu verwenden):
%Vor%Danach möchten Sie den Aktor zuweisen, der die IO auf den dedizierten Dispatcher sperrt. Sie können es in der Konfiguration tun, wie beschrieben hier oder wann Erstellen des Schauspielers:
%Vor%Um mehr Durchsatz zu erhalten, sollten Sie den blockierenden Akteur in einen Pool einfügen:
%Vor%Sie können sicherstellen, dass der Akteur den richtigen Dispatcher wie folgt verwendet:
%Vor%Sie können Futures oder vielleicht RxJava mit Observablen und Beobachtern verwenden. Oder verschiedene Akteure und leiten die endgültige Antwort an den ursprünglichen Absender weiter.
%Vor%Oder statt pipe
f.onComplete(new OnComplete<String>(){
public void onComplete(Throwable t, String result){
readFileActor.tell(result,self());
}
}, context().system().dispatcher());