2015-06-01 46 views
11

我在Akka的documentation中读到了使用集群单例时应该避免使用自动downing。 我不明白在这种情况下如何配置downing。 我知道我可以订阅集群成员事件并根据这些消息计划我的策略。但是,我不明白它与自动降档的区别。如何在存在单例时配置akka集群中的downing

当某个节点以某种方式与集群分区时,如果使用自动切换,分区节点将“认为”整个集群失踪并启动自己的集群(使用自己的单例)。但是,另一方面,我无法永远将无法访问的节点保持在不可达状态,因为集群不会达到收敛(新节点将无法加入),并且如果分区节点是单例本身,则会生成一个新的单例根据我的理解,节点将不会被分配,因此根据我的理解,唯一需要做的就是在一段宽限期后删除无法访问的节点,这正是自动降级所要做的。

我在这里错过了什么?

+0

我也有同样的问题你。看来,我们没有办法阻止2集群分区启动自己的集群辛格尔顿的评论 – mingchuno

回答

1

请看下面的代码。正如文档所述,我已关闭auto-down-unreachable-after功能。相反,我实现了一种与正常情况有点不同的自定义逻辑。下面的代码的关键是如果网络分区发生,只有拥有多数的集群节点将在一些可配置的5之后取下UnreachableMember。另一方面,少数群集节点将踩在他们的UnreachableMember(这是多数组为unreachable,并不要把它们放下来形成一个岛屿。大多数人的想法是从MongoDB借用,我认为是在计算机科学领域并不新鲜。

class ClusterListener extends Actor with ActorLogging { 

    val cluster = Cluster(context.system) 
    var unreachableMember: Set[Member] = Set() 

    // subscribe to cluster changes, re-subscribe when restart 
    override def preStart(): Unit = { 
    //#subscribe 
    cluster.subscribe(self, initialStateMode = InitialStateAsEvents, classOf[UnreachableMember], classOf[ReachableMember]) 
    //#subscribe 
    } 
    override def postStop(): Unit = cluster.unsubscribe(self) 

    def receive = { 
    case UnreachableMember(member) => 
     log.info("Member detected as unreachable: {}", member) 
     val state = cluster.state 
     if (isMajority(state.members.size, state.unreachable.size)) { 
     scheduletakeDown(member) 
     } 
    case ReachableMember(member) => 
     unreachableMember = unreachableMember - member 
    case _: MemberEvent => // ignore 
    case "die" => 
     unreachableMember.foreach { member => 
     cluster.down(member.address) 
     } 
    } 

    // find out majority number of the group 
    private def majority(n: Int): Int = (n+1)/2 + (n+1)%2 

    private def isMajority(total: Int, dead: Int): Boolean = { 
    require(total > 0) 
    require(dead >= 0) 
    (total - dead) >= majority(total) 
    } 

    private def scheduletakeDown(member: Member) = { 
    implicit val dispatcher = context.system.dispatcher 
    unreachableMember = unreachableMember + member 
    // make 5s config able!!! 
    context.system.scheduler.scheduleOnce(5 seconds, self, "die") 
    } 

} 
+0

谢谢,但我不明白的东西。当分区(少数)节点返回到大多数时,可以说网络/ gc问题已经解决,除非少数节点重新启动他们的参与者系统(为了重新生成新的令牌),他们是否能够再次连接到大多数因为据我所知如果一个节点已从集群中删除,它不能以相同的标记返回。 – Mizh

+0

你好,我知道这是旧的。但对于任何寻找答案的人来说。被大多数标记为down的分区节点将明确地必须重新启动才能再次加入集群。 http://doc.akka.io/docs/akka/2.4.2/scala/cluster-usage.html#Joining_to_Seed_Nodes – Cal

+1

我已经在Akka 2.4.3上测试过,并且已经确认它可以正常工作。我有两台机器,我在机器A上运行大部分节点,在机器B上运行少数节点。我断开A和B之间的连接以模拟分区。机器A节点对少数节点(机器B节点)发放删除,少数节点能够认识到它们实际上是少数节点。请注意,少数节点不会自行终止并继续运行。需要额外的逻辑来关闭它们。搜索“akka集群裂脑和重新连接”了解更多信息。 感谢分享@mingchuno – Cal