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

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

application.conf:

someactor {
  akka.remote.netty.tcp.port = 6405
  akka.cluster.auto-down-unreachable-after = 20s
  akka.cluster.seed-nodes = ["akka.tcp://mySys@127.0.0.1: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 вызывается из нескольких мест параллельно).

2 ответа

Решение

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

Маршрутизатор init:

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://mySys@127.0.0.1:2552"]
  cluster.roles.1 = "someActor"
  actor.provider = "akka.cluster.ClusterActorRefProvider"
}

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

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

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

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

Другие вопросы по тегам