scala - Akka单点故障

标签 scala akka akka-cluster

我想创建一个不会出现单点故障的系统。
我的印象是路由器是这样做的工具,但我不确定它是否能像我预期的那样工作。
这是我的程序的入口点:

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")
}

这是运行远程 ActorSystem 的代码(因此路由器可以将 TestActor 代码部署到远程节点):
object TestActor extends App{
  val system = ActorSystem("mySys", ConfigFactory.load("application").getConfig("testactor1"))
  case object PrintRouterPath
}

我运行了两次,一次是 testactor1和一次 testactor2 .
TestActor代码:
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}")
  }
}

和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://mySys@127.0.0.1:2552"
    "akka.tcp://mySys@127.0.0.1:2553"
    "akka.tcp://mySys@127.0.0.1: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://mySys@127.0.0.1:2552"
        "akka.tcp://mySys@127.0.0.1:2553"
        "akka.tcp://mySys@127.0.0.1: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://mySys@127.0.0.1:2552"
        "akka.tcp://mySys@127.0.0.1:2553"
        "akka.tcp://mySys@127.0.0.1:2554"]
      auto-down-unreachable-after = 20s
    }
  }
}

现在的问题是,当启动路由器的进程被杀死时,运行 TestActor 代码的actor ,没有收到任何消息(调度程序发送的消息),我希望路由器将部署在集群中的另一个种子节点上,并且参与者将被恢复。这可能吗?或者有没有其他方法可以实现这个流程并且没有单点故障?

最佳答案

我认为,通过部署 router仅在一个节点上设置主从集群,根据定义,主节点是单点故障。

据我所知(查看 docs ),路由器可以感知集群,因为它可以在集群中的节点上部署(池模式)或查找(组模式)路由。路由器本身不会通过在集群中的其他地方生成来对故障使用react。

我相信你有两个选择:

  • 利用多个路由器使您的系统更容错。路由可以在路由器之间共享(组模式)或不共享(池模式)。
  • 使用 Cluster Singleton模式 - 允许主从配置,如果发生故障,主服务器将自动重新生成。关于您的示例,请注意,此行为是通过在每个节点中部署一个参与者 ( ClusterSingletonManager ) 来实现的。这个 actor 的目的是确定是否需要重生所选的 master 以及在哪里。对于像您设置的那样的集群感知路由器,这些逻辑都没有到位。

  • 您可以在此 Activator sample 中找到多个集群设置的示例.

    关于scala - Akka单点故障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41783548/

    相关文章:

    java - 如何在不使用 Thread.sleep 命令的情况下执行 akka actor 中的整个代码?

    Akka Singleton - 不接受消息

    java - 用于字符串处理的 Akka 分散-聚集

    docker - 自动化微服务负载平衡/缩放

    scala - 如何在 scalaz 中导入身份操作?

    arrays - 在 Scala 中为数组添加值

    java - Apache Mailer 在 Scala 中抛出编译器错误?

    scala - sbt:抑制标准输出中的日志前缀

    scala - 如何使用 react 性流进行NIO二进制处理?

    unit-testing - 使用 Mockito 模拟 Akka Actor 日志对象