首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Akka单点故障

Akka单点故障
EN

Stack Overflow用户
提问于 2017-01-21 19:27:59
回答 2查看 750关注 0票数 5

我想要建立一个系统,它不会有一个单一的故障点。我当时的印象是路由器是这样做的工具,但我不确定它是否如我所期望的那样工作。这是我的项目的切入点:

代码语言:javascript
复制
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代码部署到远程节点):

代码语言:javascript
复制
object TestActor extends App{
  val system = ActorSystem("mySys", ConfigFactory.load("application").getConfig("testactor1"))
  case object PrintRouterPath
}

我要运行这两次,一次用testactor1,一次用testactor2

TestActor代码:

代码语言:javascript
复制
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

代码语言:javascript
复制
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代码的参与者没有接收到任何消息(调度程序发送的消息),我希望路由器将部署在集群中的另一个种子节点上,并且将恢复参与者。这个是可能的吗?或者有没有其他的方法来实现这个流程,而没有一个单一的失败点?

EN

回答 2

Stack Overflow用户

发布于 2017-01-26 16:34:04

我认为,通过只在一个节点上部署router,您将设置一个主从集群,其中主节点定义为单个故障点。

据我所知(查看文档),路由器可以感知集群,因为它可以在集群中的节点上部署(池模式)或查找(组模式)路由器。路由器本身不会通过在集群中其他地方生成而对失败作出反应。

我相信你有两个选择:

  1. 利用多个路由器,使您的系统更容错。路由器可以共享(组模式),也可以不(池模式)在路由器之间共享。
  2. 利用簇单例模式--它允许主从配置,在发生故障时,主程序将被自动重新生成。对于您的示例,请注意,此行为是通过在每个节点中部署一个参与者(ClusterSingletonManager)来实现的。这位演员的目的是想弄清楚选择的主人是否需要重生,以及在哪里。在集群感知路由器的情况下,所有这些逻辑都不适用于您设置的路由器。

您可以在此活化剂样品中找到多个集群设置的示例。

票数 2
EN

Stack Overflow用户

发布于 2017-01-30 20:34:31

我测试了两种方法,第一种是在ClusterRouterPool中使用您的代码,正如您所说的,当启动路由器的进程被终止时,TestActor没有收到更多的消息。在阅读文档和测试时,如果您更改了application.conf

代码语言:javascript
复制
`auto-down-unreachable-after = 20s` 

为此

代码语言:javascript
复制
`auto-down-unreachable-after = off`

TestActor一直在接收消息,尽管在日志中出现了以下消息(对不起,我不知道如何将日志放在这里):

警告mySys-akka.emote.Default- remote -dispatcher-5关联远程系统akka.tcp://mySys@127.0.0.1:2552已失败,地址现在关闭为5000 ms。原因:[联系失败与akka.tcp://mySys@127.0.0.1:2552]:连接被拒绝: akka.tcp://mySys@127.0.0.1:2554/remote/akka.tcp/mySys@127.0.0.1:2552/user/testActors/c1 01/30/2017 :20:20:29.860 Actorakka.tcp://mySys@127.0.0.1:2552/user/testActors路由器在路径上#-1120251475 01/30/2017 17:20:32.016

在重新启动MainApp的情况下,日志正常工作,没有警告或错误。

MainApp日志:

信息mySys-akka.actor.default-2群集节点akka.tcp://mySys@127.0.0.1:2552 -欢迎来自akka.tcp://mySys@127.0.0.1:2554

TestActor日志:

信息[ 01/30/2017 17:23:21.958 akka.cluster.Cluster(akka://mySys)群集Node akka.tcp://mySys@127.0.0.1:2554 -现有成员的新化身(地址= akka.tcp://mySys@127.0.0.1:2552,status = Up)正在尝试加入。现有成员将从集群中删除,然后允许新成员加入。信息mySys-akka.actor.Default-14群集节点akka.tcp://mySys@127.0.0.1:2554 -标记不可到达的节点akka.tcp://mySys@127.0.0.1:2552 as Down 01/30/2017 17:23:22.454 akka.cluster.Cluster(akka://mySys)群集Nodeakka.tcp://mySys@127.0.0.1:2554-领导人可以再次执行其职责-mySys-akka.actor.defaulcher-2集群节点阿克卡。tcp://mySys@127.0.0.1:2554 -领导人正在删除无法到达的节点akka.tcp://mySys@127.0.0.1:2552 01/30/2017 17:23:32.728 akka.cluster.Cluster(akka://mySys)群集节点akka.tcp://mySys@127.0.0.1:2554 - node akka.tcp://mySys@127.0.0.1:2552正在加入,角色01/30/2017 17:23:33.457 akka.cluster.Cluster(akka://mySys)集群节点akka.tcp://mySys@127.0.0.1:2554 -领导人正在将节点akka.tcp://mySys@127.0.0.1:2552移动到01/30/2017 :23:37.925 akka.tcp://mySys@127.0.0.1:2554/remote/akka.tcp/mySys@127.0.0.1:2552/user/testActors/Actorakka.tcp://mySys@127.0.0.1:2552/user/testActors#-630150507路径上的c1路由器

另一种方法是使用ClusterRouterGroup,因为路由器是在集群的节点之间共享的。

  • 组路由器,它使用参与者选择将消息发送到指定的路径,路由器可以在集群中不同节点上运行的路由器之间共享。这种类型路由器的用例之一是运行在集群中某些后端节点上的服务,并由集群中前端节点上运行的路由器使用。
  • 池路由器,它将路由器创建为子参与者,并将它们部署到远程节点上。每个路由器都有自己的路由实例。例如,如果您在一个10节点集群中的3个节点上启动一个路由器,如果该路由器配置为每个节点使用一个实例,那么总共将有30个路由器。由不同路由器创建的路由器不会在路由器之间共享。这种类型路由器的一个用例是一个主服务器,它协调作业并将实际工作委托给集群中其他节点上运行的路由器。

主应用程序

代码语言:javascript
复制
object Main extends App {

  val system = ActorSystem("mySys", ConfigFactory.load("application.conf"))
  val routerGroup = system.actorOf(
ClusterRouterGroup(RoundRobinGroup(Nil), ClusterRouterGroupSettings(
  totalInstances = 2, routeesPaths = List("/user/testActor"),
  allowLocalRoutees = false, useRole = Some("testActor"))).props(),
name = "testActors")
}

必须在每个远程节点中启动TestActor

代码语言:javascript
复制
object TestActor extends App{
  val system = ActorSystem("mySys", ConfigFactory.load("application").getConfig("testactor1"))
  system.actorOf(Props[TestActor],"testActor")
  case object PrintRouterPath
}

鲁特斯

路由器在启动参与者系统时应尽早启动路由器,因为一旦成员状态更改为“Up”,路由器就会尝试使用它们。

我希望它能帮到你

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41783548

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档