2013-07-28 79 views

回答

15

你其實並不需要訂閱ClusterDomainEventMemberEvent。你可以只訪問羣集擴展的state成員,例如,

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

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

根據我的經驗(我認爲這是在某處的文檔中提到)以這種方式獲取狀態不保證同步。如果你需要一個更準確的狀態圖,你需要像Patrik Nordwall所建議的那樣,解析集羣監聽器中的事件。 – jm0

+0

以我的經驗,你不能在同一個演員中混用這兩個成語。由於消息在郵箱中的滯留時間,響應接收中的羣集事件保證落後於實際羣集狀態。 –

+0

thx澄清 - 我的使用案例,雖然是我需要執行裂腦分辨率,當一個成員被刪除,那麼如果不是自我管理,在這種情況下如何獲得最新的狀態?我不認爲這是關於成語的混合,更多的是以這種方式獲得狀態不能被信任。我認爲可以訂閱的ClusterState域事件會更準確(因爲系統正在通過監聽器提交整型狀態),但可能落後於按需狀態方法的響應需要多長時間改變。 – jm0

4

一種方法可能是有另一個演員訂閱到ClusterDomainEvent信息,專門尋找通過CurrentClusterState事件的成員。這可能是這個樣子:

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

這是怎樣的一個粗線條的(可能需要一些調整),但在這裏,是希望所有的演員要知道目前的成員名單可以發送GetMembers消息,這演員通過?並等待迴應。

現在這種方法假定你可能有許多演員想要這個信息。如果事實證明你只有一個演員想要這個信息,那麼只需讓該演員訂閱該事件並更新其成員的內部狀態。從Typesafe Activator tutorial

+0

的訂閱演員, 'ClusterMemberHolder'還必須處理'MemberUp'和'MemberRemoved'事件。 publishCurrentClusterState不是必需的。 –

8

調整了樣本:

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