Chcę stworzyć system, który nie będzie miał pojedynczego punktu awarii. Miałem wrażenie, że routery są narzędziem do robienia tego, ale nie jestem pewien, czy działa tak, jak bym się spodziewał. Jest to punkt wejścia mojego programu:Akka pojedynczy punkt awarii
object Main extends App{
val system = ActorSystem("mySys", ConfigFactory.load("application"))
val router = system.actorOf(
ClusterRouterPool(RoundRobinPool(0), ClusterRouterPoolSettings(
totalInstances = 2, maxInstancesPerNode = 1,
allowLocalRoutees = false, useRole = Some("testActor"))).props(Props[TestActor]),
name = "testActors")
}
I jest to kod do uruchomienia zdalnego ActorSystem
(tak, router mógł wdrożyć kod TestActor
do odległych węzłów):
object TestActor extends App{
val system = ActorSystem("mySys", ConfigFactory.load("application").getConfig("testactor1"))
case object PrintRouterPath
}
I uruchomiłem to dwukrotnie, raz z testactor1
i raz z testactor2
.
TestActor
Kod:
class TestActor extends Actor with ActorLogging{
implicit val ExecutionContext = context.dispatcher
context.system.scheduler.schedule(10000 milliseconds, 30000 milliseconds,self, PrintRouterPath)
override def receive: Receive = {
case PrintRouterPath =>
log.info(s"router is on path ${context.parent}")
}
}
I application.conf
akka{
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2552
}
}
cluster {
seed-nodes = [
"akka.tcp://[email protected]:2552"
"akka.tcp://[email protected]:2553"
"akka.tcp://[email protected]:2554"]
auto-down-unreachable-after = 20s
}
}
testactor1{
akka{
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2554
}
}
cluster {
roles.1 = "testActor"
seed-nodes = [
"akka.tcp://[email protected]:2552"
"akka.tcp://[email protected]:2553"
"akka.tcp://[email protected]:2554"]
auto-down-unreachable-after = 20s
}
}
}
testactor2{
akka{
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2553
}
}
cluster {
roles.1 = "testActor"
seed-nodes = [
"akka.tcp://[email protected]:2552"
"akka.tcp://[email protected]:2553"
"akka.tcp://[email protected]:2554"]
auto-down-unreachable-after = 20s
}
}
}
Teraz problemem jest to, że gdy proces, który rozpoczął się router zostaje zabity, aktorzy, które są uruchomione kod TestActor
, nie otrzymują żadnych wiadomości (wiadomości wysyłanych przez program planujący), oczekiwałbym, że router zostanie wdrożony w innym węźle źródłowym w klastrze, a aktorzy zostaną odzyskani. czy to możliwe? lub czy istnieje inny sposób wdrożenia tego przepływu i braku pojedynczego punktu awarii?
1) powiedzmy, że mam dwa węzły działające testActor następnie proponujesz zacząć router na każdego z nich (grupa mieć dokładnie te same dwie instancje na każdym routerze). jak mam teraz korzystać z routera? Chodzi mi o to, jaki będzie cel używania go? jeśli chcę wysłać wiadomość rozgłoszeniową do rutowanych, wyślę wiadomość do jednego z węzłów zawierających router (a ten węzeł może być niedostępny) lub wyślę do wszystkich z nich, a następnie otrzymam obsługę wielu komunikatów. Czy czegoś brakuje? 2) Jeśli używam 'ClusterSingletonManager' nie znaczy to, że nie mogę uruchomić dwóch aktorów z' TestActor'? –