АККА - как заблокировать создание актера, если его имя не уникально в кластере
Я пытаюсь заблокировать возможность присутствия в системе актеров с одинаковым именем (они находятся на разных путях, поэтому 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 для доступа к рабочему пулу.