2013-07-28 15 views

Odpowiedz

15

rzeczywiście nie trzeba subskrybować ClusterDomainEvent lub MemberEvent. Można tylko dostęp członu state rozszerzenia Cluster np

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

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

Z mojego doświadczenia (i myślę, że jest to gdzieś wspomniane w dokumentach) uzyskanie stanu w ten sposób nie gwarantuje synchronizacji. Jeśli potrzebujesz dokładniejszego obrazu stanu, powinieneś zrobić coś takiego, jak sugeruje Patrik Nordwall, parsowanie zdarzeń w słuchaczu klastra. – jm0

+0

Z mojego doświadczenia wynika, że ​​nie można mieszać dwóch idiomów tego samego aktora. Reagowanie na zdarzenia klastrowania w odbiorze jest gwarantowane za rzeczywistym stanem klastra ze względu na opóźnienie wiadomości wiszących w skrzynkach pocztowych. –

+0

thx dla wyjaśnienia - moim przypadkiem użycia jest jednak to, że muszę wykonać podział rozdzielczości mózgu, gdy członek jest usunięty, więc w jaki sposób można uzyskać najbardziej aktualny stan w tej sytuacji, jeśli nie jest samodzielny? Nie sądzę, że chodzi o mieszanie idiomów, więcej, że uzyskanie stanu w ten sposób nie może być zaufane. Wydaje mi się, że zdarzenie w domenie ClusterState, które może być subskrybowane, byłoby bardziej dokładne (ponieważ system sam sobie radzi z przesyłaniem stanów wholistycznych za pośrednictwem odbiornika), ale prawdopodobnie pozostaje w tyle z czasem, w jakim zajmuje tę metodę odpowiedzi na żądanie. zmienić. – jm0

4

Jednym ze sposobów może być mieć inny aktor subskrybować do ClusterDomainEvent wiadomości, a konkretnie szuka członków poprzez imprezy CurrentClusterState. To może wyglądać mniej więcej tak:

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 
    } 
} 

Jest to rodzaj szorstkiej zarysu (może potrzebować kilku poprawek), ale stąd, każdy aktor, który chciał znać listę obecnych członków może wysłać wiadomość GetMembers temu aktor przez ? i czekać na odpowiedź.

Teraz to podejście zakłada, że ​​możesz mieć wielu aktorów, którzy chcą tych informacji. Jeśli okaże się, że masz tylko jednego aktora, który chce tych informacji, to po prostu poproś tego aktora, aby zasubskrybował to wydarzenie i zaktualizował jego wewnętrzny stan z członkami.

+0

sygnatariuszy aktora, 'ClusterMemberHolder' musi również obsługiwać zdarzenia' MemberUp' i 'MemberRemoved'. publicCurrentClusterState nie jest potrzebny. –

8

Tweaked próbka z 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 
    } 
} 
Powiązane problemy