AKKA- как заблокировать создание актора если его имя не уникально в кластере

Я пытаюсь заблокировать возможность наличия в системе актеров с одинаковым именем (они находятся на разных путях, поэтому InvalidActorNameException не будет выброшено)

приложение.conf:

someactor {
  akka.remote.netty.tcp.port = 6405
  akka.cluster.auto-down-unreachable-after = 20s
  akka.cluster.seed-nodes = ["akka.tcp://[email protected]:2552"]
  akka.actor.provider = "akka.cluster.ClusterActorRefProvider"
}

Главный:

object SomeActor extends App {
  val system  =  ActorSystem("mySys", ConfigFactory.load("application").getConfig("someactor"))
  val t = system.actorOf(Props(classOf[SomeActor]), "someActor")
}

Актер:

class SomeActor extends Actor {
    val cluster = Cluster(SomeActor.system)
    override def receive = {
       case x=> println(x)
    }
}

Если вы запустите приложение один раз с портом 6405 и один раз с портом 6406, тогда приложение будет работать, но я хочу, чтобы оно заметило, что в системе уже есть актор с именем «someActor», и заблокировало этот вызов.

Я не против добавить имя в качестве роли или в другую конфигурацию, если оно сможет заблокировать это, но я не могу иметь состояние, подобное карте, содержащей уже существующие имена (или актер, содержащий карту с передачей сообщений ) или иметь длительную операцию, такую ​​​​как actorSelection (и в любом случае они не будут безопасны, если actorOf вызывается из нескольких мест параллельно).


person user_s    schedule 03.01.2017    source источник
comment
Звучит как подход, склонный к условиям гонки. Что, если оба актора созданы в один и тот же момент времени на разных узлах? Итак, может быть, объясните, чего вы хотите достичь в первую очередь? (Вы ищете что-то вроде ClusterSingleton? ClusterSingleton содержит аналогичную проверку, при которой синглтоны должны жить на самом старом узле, который, как известно, согласован всеми узлами в кластере.)   -  person jrudolph    schedule 03.01.2017
comment
Я думаю, что вы действительно ищете, это сегментирование кластера и/или кластерные синглтоны.   -  person Ryan    schedule 03.01.2017
comment
Поправьте меня, если я ошибаюсь, но разве кластерный синглтон не блокирует создание акторов по их типу? если это так, это не сработает для меня, потому что я хочу создать много актеров класса SomeActor, я просто не хочу, чтобы эти актеры имели одно и то же имя (это имя является уникальным идентификатором, который у меня есть в моей программе для каждого рабочего актера, поэтому у меня не может быть дубликатов)   -  person user_s    schedule 04.01.2017


Ответы (2)


Если вам действительно нужны 100% непересекающиеся UUID, почему бы вам просто не создать единую службу для назначения UUID и не получить свой UUID перед созданием актера?

Вы также можете использовать хэш SHA для имени хоста, порта и имени актера, а также увеличивающийся рабочий номер для каждого актера.

Вы также можете настроить Cluster Router для воркеров, и akka сделает все это за вас, и вам нужно будет только отправить на один ActorRef доступ к пулу воркеров.

person XGoVoid    schedule 03.01.2017
comment
Уникальный идентификатор уже существует в системе, поэтому я не могу создать свой собственный. - person user_s; 04.01.2017

Мне удалось сделать это с помощью Cluster Aware Router типа group (каждый актор будет работать на удаленном узле). Роль ноды - имя "someActor", я инициализирую актор на удаленной ноде с тем же именем "someActor"(так я буду знать какой путь к этому актору) и конфиг totalInstances роутера равен 1( поэтому только один узел будет частью маршрутизатора)

Инициализация роутера:

context.actorOf(
        ClusterRouterGroup(RoundRobinGroup(Nil), ClusterRouterGroupSettings(
          totalInstances = 1, routeesPaths = List("/user/someActor"),
          allowLocalRoutees = false, useRole = Some("someActor"))).props()

Удаленный актер:

object RemoteActor extends App{
  val system = ActorSystem("mySys",ConfigFactory.load("remoteActorConfig"))
  system.actorOf(Props[RemoteActor], "someActor")

}

class RemoteActor extends Actor with ActorLogging{
  override def receive: Receive = {
    case x =>
      log.info(s"got: $x}")
  }
}

и remoteActorConfig :

akka{
  remote.netty.tcp.port = 0
  cluster.auto-down-unreachable-after = 20s
  cluster.seed-nodes = ["akka.tcp://[email protected]:2552"]
  cluster.roles.1 = "someActor"
  actor.provider = "akka.cluster.ClusterActorRefProvider"
}

Теперь, если я дважды запущу RemoteActor, запущу приложение, которое инициализирует маршрутизатор и отправит широковещательное сообщение на маршрутизатор, его получит только один актор RemoterActor (и всегда один и тот же).

person user_s    schedule 20.01.2017