2013-07-28 13 views

Antwort

15

Sie brauchen eigentlich nicht zu ClusterDomainEvent oder MemberEvent abonnieren. Sie können nur Zugriff auf das state Mitglied der Cluster-Erweiterung, zum Beispiel

val cluster = akka.cluster.Cluster(context.system) 

val members = cluster.state.members.filter(_.status == MemberStatus.Up) 
+1

Nach meiner Erfahrung (und ich denke, dass dies in den Dokumenten irgendwo erwähnt wird) ist es nicht garantiert, dass der Status auf diese Weise synchron ist. Wenn Sie ein genaueres Bild des Zustands benötigen, müssen Sie etwas tun, wie es Patrik Nordwall vorschlägt, indem Sie Ereignisse in einem Cluster-Listener analysieren. – jm0

+0

Nach meiner Erfahrung können Sie die beiden Idiome nicht in demselben Akteur mischen. Das Reagieren auf Cluster-Ereignisse in Empfang ist aufgrund der Latenz von Nachrichten in Postfächern garantiert hinter dem tatsächlichen Cluster-Status. –

+0

thx zur Klarstellung - mein Anwendungsfall ist jedoch, dass ich Split-Brain-Auflösung durchführen muss, wenn ein Mitglied entfernt wird, also wie kann der aktuellste Zustand in dieser Situation erreicht werden, wenn nicht Selbstverwaltung? Ich denke nicht, dass es um das Mischen von Idiomen geht, mehr, dass man auf diese Weise keinen Status bekommen kann, kann man nicht vertrauen. Ich denke, da ist ein ClusterState-Domain-Event, das abonniert werden kann, wäre genauer (da System es auf sich nimmt, über einen Listener ganzheitliche Zustände zu übermitteln), aber wahrscheinlich auf Augenhöhe mit der Reaktionszeit dieser On-Demand-State-Methode wechseln. – jm0

4

Ein Ansatz könnte sein, eine andere Schauspieler haben in ClusterDomainEvent Nachrichten abonnieren, die speziell für die Mitglieder über das CurrentClusterState Ereignis suchen. Das könnte wie folgt aussehen:

case object GetMembers 

class ClusterMembersHolder extends Actor{ 
    var members:Set[Member] = Set() 
    override def preStart = { 
    val clusterSys = Cluster(context.system) 
    clusterSys.subscribe(self, classOf[ClusterDomainEvent]) 
    clusterSys.publishCurrentClusterState //Forces the current state 
    } 

    def receive = { 
    case state: CurrentClusterState => 
     members = state.members 

    case GetMembers => 
     sender ! members 
    } 
} 

Diese Art einer groben Umriss ist (vielleicht ein paar Veränderungen müssen), aber von hier, jeder Akteur, der die aktuelle Mitgliederliste könnte eine GetMembers Nachricht senden, dies wissen wollten Schauspieler über ? und warten auf die Antwort.

Jetzt geht dieser Ansatz davon aus, dass Sie viele Akteure haben, die diese Informationen wünschen. Wenn sich herausstellt, dass Sie nur einen Akteur haben, der diese Information haben möchte, dann müssen Sie diesen Akteur nur bei diesem Event anmelden und seinen internen Status mit den Mitgliedern aktualisieren.

+0

Der unterzeichnende Schauspieler, 'ClusterMemberHolder' muss außerdem' MemberUp'- und 'MemberRemoved'-Ereignisse behandeln. publishCurrentClusterState wird nicht benötigt. –

8

Gezwickt Probe aus Typesafe Activator tutorial:

case object GetNodes 

class MemberListener extends Actor { 

    val cluster = Cluster(context.system) 

    override def preStart(): Unit = 
    cluster.subscribe(self, classOf[MemberEvent]) 

    override def postStop(): Unit = 
    cluster unsubscribe self 

    var nodes = Set.empty[Address] 

    def receive = { 
    case state: CurrentClusterState => 
     nodes = state.members.collect { 
     case m if m.status == MemberStatus.Up => m.address 
     } 
    case MemberUp(member) => 
     nodes += member.address 
    case MemberRemoved(member, _) => 
     nodes -= member.address 
    case _: MemberEvent ⇒ // ignore 
    case GetNodes => 
     sender ! nodes 
    } 
}