Как настроить отключение в кластере akka при наличии синглтона

Я читал в документации Akka, что при использовании синглтона кластера следует избегать использования автоматического отключения . Я не понимаю, как в таком случае настраивать сбой. Я понимаю, что могу подписаться на события членства в кластере и планировать свою стратегию в соответствии с этими сообщениями. Однако я не понимаю, чем это будет практически отличаться от автоматического сбития.

Когда узел каким-либо образом отделен от кластера, если используется автоматическое отключение, секционированный узел будет «думать», что весь кластер пропал, и запускать собственный кластер (со своим собственным синглтоном). Но, с другой стороны, я не могу вечно держать недостижимые узлы в недостижимом состоянии, потому что кластер не достигнет сходимости (новые узлы не смогут присоединиться), и если секционированный узел сам является одноэлементным, то новый одноэлементный узел не будет назначен, и поэтому, согласно моему пониманию, единственное, что осталось сделать, - это удалить недостижимые узлы по истечении некоторого времени отсрочки, что и делает автоматическое отключение.

Что мне здесь не хватает?


person Mizh    schedule 01.06.2015    source источник
comment
У меня такой же вопрос, как и у вас. Похоже, у нас нет возможности предотвратить запуск двух кластерных разделов собственного Cluster Singleton   -  person mingchuno    schedule 03.06.2015


Ответы (1)


ознакомьтесь с приведенным ниже кодом. Я отключил функцию auto-down-unreachable-after, как сказано в документе. Вместо этого я реализую собственную логику, которая немного отличается от обычной. Ключевым моментом приведенного ниже кода является то, что если произойдет разделение сети, только узлы кластера, которые имеют большинство, будут отключены UnreachableMember после некоторых настраиваемых 5 секунд. С другой стороны, меньшинство узлов кластера будет наступать на их 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")
  }

}
person mingchuno    schedule 04.06.2015
comment
Спасибо за комментарий, но я чего-то не понимаю. Когда разделенные (меньшие) узлы вернутся к большинству, скажем, проблемы с сетью / gc были решены, если только второстепенные узлы не перезапустят свою систему акторов (чтобы регенерировать новый токен), смогут ли они снова подключиться к большинству? потому что, насколько мне известно, если узел был удален из кластера, он не может вернуться с тем же токеном. - person Mizh; 04.06.2015
comment
Привет, я знаю, что это старое. Но для тех, кто ищет ответ. Секционированные узлы, которые были отмечены большинством как отключенные, должны были быть явно перезапущены, чтобы снова присоединиться к кластеру. doc.akka.io/docs/akka/ 2.4.2 / scala / - person Cal; 22.02.2016
comment
Я протестировал это на Akka 2.4.3 и подтвердил, что он работает. У меня две машины, я запускаю большинство узлов на машине A и меньшинство на машине B. Я разрываю соединение между A и B, чтобы имитировать раздел. Узлы машины A выдают уничтожение меньшинства (узлы машины B), и узлы меньшинства могут понять, что они на самом деле составляют меньшинство. Обратите внимание, что второстепенные узлы не завершают работу и продолжают работать. Чтобы отключить их, нужна дополнительная логика. Найдите akka cluster split brain и переподключитесь для получения дополнительной информации. Спасибо, что поделились @mingchuno - person Cal; 09.04.2016
comment
Подтверждаете ли вы из любопытства, что такой актор необязательно запускать на всех машинах кластера? Думаю, если он работает на тех же узлах, что и те, на которых есть экземпляр Singleton, этого достаточно, не так ли? - person CanardMoussant; 24.11.2016