2013-05-20 11 views
11

Würdest du einen schönen Weg in Akka/Scala zum Hinzufügen/Entfernen von Routes zu einem Broadcaster-Router kennen?Dynamische Hinzufügen/Entfernen von Routes zu einem Router-Actor

Ich habe mir den Resizer angeschaut - aber nicht meine Bedürfnisse (ich kann nicht sehen, wie man den Resizer explizit dazu anfordert, die Größe zu ändern (routees hinzufügen) und zu entfernen scheint, dass man dem Akteur eine Giftpille schicken muss welches dann entfernt wird).

Bisher habe ich einen Router mit einer Liste von ActorRef und ich schicke AddRoutee und RemoveRoutee Nachrichten ....

Mein Business Case: Ich habe einen Schauspieler Daten aus dem Netz bekommen (über einen Proxy) und muss diese Daten an unabhängige Akteure zur parallelen Verarbeitung senden. Aufgrund der Diagrammnatur der Empfänger (DAG) kann sich der Graph zur Laufzeit entwickeln, Scheitelpunkte/Kanten werden modifiziert, daher müssen Routen hinzugefügt und entfernt werden

Es muss einen saubereren Weg geben, dies zu tun.

Danke für die Zeiger.

Beispiel für Code, den ich Akka zu handhaben möchte:

class MDActor extends Actor { 
    @volatile var routees = Set[ActorRef]() 

    def receive = { 
    case ar: AddRoutee => routees = routees + ar.actorRef 
    case rr: RemoveRoutee => routees = routees - rr.actorRef 
    case msg => routees.foreach(r => r forward msg) 
    } 
} 
+0

Können Sie etwas mehr Kontext in die Situation (en) in Ihrem Code eingeben, die zum Hinzufügen/Entfernen von Routen vom Router führen? Diese Art von Informationen wird helfen, Lösungen zu finden. – cmbaxter

+1

In Ihrem Beispiel würde ich Set [ActorRef] anstelle von List [ActorRef] empfehlen, um Routes Duplikation zu verhindern. Und benutze "vorwärts" statt "!" um den ursprünglichen Absender zu bewahren. –

+0

Danke. Das ist eine großartige Idee. – jts

Antwort

2

Wenn Sie feststellen, dass Ihnen ein Feature in einem Router fehlt, ist es ein guter Zeitpunkt, um in die andere Richtung zu denken: Was stimmt nicht mit dem Code, den Sie präsentieren? Wenn Sie nicht mehr als ein paar Millionen Nachrichten pro Sekunde routen müssen (was Ihrer Beschreibung nach unwahrscheinlich ist), ist ein solcher Akteur genau die richtige Lösung. Router sind ein sehr spezialisiertes Konstrukt, das nicht als Ersatz verwendet werden sollte; verwende sie nur, wenn sie genau deinen Anforderungen entsprechen und du hast festgestellt, dass ein normaler Schauspieler nicht ausreicht.

+0

Roland, mein Anwendungsfall ist sehr spezifisch .. sogar für "Java". Das obige Muster funktioniert also gut für das, was mein Code tun soll. In der Tat, ich hätte es auf Java machen können ... was wäre der Spaß dabei? – jts

+0

Ich verstehe diesen Kommentar nicht, da ich in meiner Antwort nicht über Java gesprochen habe. Meine Antwort läuft auf "du hast es herausgefunden, hör auf zu schauen" ;-) –

+0

Nein. Immer schauen, ob es einen besseren Weg gibt, Sachen zu machen :-) – jts

1

nicht sicher, dass es wirklich ein besserer Weg als Staat über die routees zu halten und einen neuen Router bei jeder Änderung bauen oder benutzen Sie nicht ein Router und verwenden Sie einen einfachen Schauspieler. Ich habe mir das auch kürzlich angeschaut. Die favorisierte Lösung wird wahrscheinlich darin bestehen, den alten Router und/oder die Sammlung wegzuwerfen und einen neuen zu bauen (Router oder Set/Karte von Aktoren).

Bevorzugung der Unveränderlichkeit -

Sie können Ihre Aktoren einfach verfolgen und den Router überhaupt nicht verwenden - dies ist eine gute Lösung und wird in der akka Dokumentation als einfachere Alternative zu einem Router empfohlen. Router sollen einen Leistungsvorteil gegenüber einem vollwertigen Schauspieler haben.

Sie können Router mit Listen von Aktoren erstellen, wie hier gezeigt. Tun Sie dies einfach jedes Mal, wenn sich etwas ändert. (Quelle: akka Dokumentation - http://doc.akka.io/docs/akka/snapshot/scala/routing.html)

val actor1 = system.actorOf(Props[ExampleActor1]) 
val actor2 = system.actorOf(Props[ExampleActor1]) 
val actor3 = system.actorOf(Props[ExampleActor1]) 
val routees = Vector[ActorRef](actor1, actor2, actor3) 
val router2 = system.actorOf(Props().withRouter(
    RoundRobinRouter(routees = routees))) 

zeigt hier den Roundrobin-Router, aber das ist nicht anders als die Sendung einer verwenden.

Es ist ein bisschen funktionaler, um das neu zu erstellen.

+0

Funktioniert das tatsächlich? Ich sehe Fehler beim Instanziieren der Router. – mbseid

+0

Nun, stellen Sie sicher, dass die Version von akka Sie verwenden:) Beachten Sie auch die eine und einzige Roland Kuhn beantwortet :) Wir haben Arrays von Schauspieler Refs neu erstellt, die wir zufällig beim Erstellen einer Orchestrierung/Kommunikation Bibliothek gesendet. Das erneute Erstellen von Routern könnte ebenfalls möglich sein. – JasonG

+0

Gotcha. Ich habe mehr auf die tatsächliche Zusammenstellung der obigen Aussage geachtet. Ich musste Props.empty benutzen. Es war wahrscheinlich eine Versionssache. – mbseid