1

我正在尝试使用 akka 集群( http://doc.akka.io/docs/akka/2.3.9/scala/cluster-usage.html )将 Akka 应用程序从单层重构为多层结构。在应用程序中有一些具有参数化默认构造函数的参与者,例如

class MyActor(someParam: boolean = true) extends Actor {
    def receive = { /* message handling here... */ }
}

我现在正在尝试创建一个通用路由器参与者,它将路由到具有特定节点的节点。集群配置基于 akka 站点上的示例工作,我可以创建一个具有 1 个角色的路由器,该路由器路由到另一个角色的参与者:

class MyActorProxy extends Actor {
  val workerRouter = context.actorOf(FromConfig.props(Props(classOf[MyActor]), name = "workerRouter")
  def receive = {
    case msg: Any =>
      val currentSender = sender()
      workerRouter.tell(msg, currentSender)
  }
}

此方法根据需要起作用。但是,我需要去创建一些具有相同功能的代理类,这很痛苦。我正在努力让它更好地工作,有限的 scala 经验使它变得困难。这是我想做的事情:

abstract class RouterProxy[T <: Actor](routerPath: String) extends Actor {
  val router = context.actorOf(FromConfig.props(Props(classOf[T])),name=routerPath)
  def receive = {
     case msg: Any => {
       val currentSender = sender()
       router.tell(msg,currentSender)
     }
  } 
}

class MyActorProxy extends RouterProxy[MyActor](routerPath = "myActorRouter")

通过阅读一些 scala 文档和通过 stackoverflow 提出了这一点,但似乎无法做到这一点 - 这种方法不允许我为演员创建道具。我已经看到如何在 Scala 中实例化由类型参数表示的类型实例,我认为类型信息正在丢失(类型擦除)。

我将如何将演员类传递给路由器代理以允许路由器初始化?

这是我在编译期间遇到的错误,同时初始化路由器:

class type required but T found

编辑

使用通用代理路由器的背景

这种方法的原因是为单层和多层架构重构应用程序。运行多层时,我想跳过初始化任何“重”演员。鉴于我在前端节点上有以下配置:

akka.actor.deployment {
  /workerRouter {
    routee.paths = ["/user/myActor"]
    cluster.use-role = backend
  }
}

akka.cluster.roles = [frontend]

并且后端节点的角色为[backend],那么当我启动前端节点时,MyActor 将不会被初始化。MyActor 是许多作为主管/经理的参与者之一的示例。它们中的每一个都可能轮流初始化一些其他参与者(有时使用路由器)。我正在尝试做的是重构应用程序,以便我可以在不同层中运行轻量级前端节点,以在需要时运行资源繁重的后端节点,但仍然能够在单个节点上运行所有节点。通过这种方法,我可以将重型管理器的初始化添加到我的应用程序引导程序中并添加一个角色,它成为一个多功能应用程序而无需重新编码。

编辑 2 如果类构造函数不接受任何参数,我可以让应用程序按预期工作。

MyActor extends Actor { /* ... */ }

然后在我的抽象类中:

abstract class RouterProxy[T <: Actor](routerPath: String) extends Actor {
  val router = context.actorOf(FromConfig.props(Props[T]),name = routerPath)
}

Props[MyActor]对于无参数的演员来说效果很好,但Props(classOf[T])会丢失类型。

4

1 回答 1

1

您实际上不必为路由器定义另一个类,您可以通过配置文件完成所有操作:

val myActorRouter = system.actorOf(Props[MyActor]
      .withRouter(FromConfig())
      ,"workerRouter")

其中“workerRouter”在您的 application.conf 文件中定义如下:

akka.actor.deployment {
  /workerRouter {
    router = round-robin
    nr-of-instances = 5
  }
}

如果你有一个非常简单的配置,你也可以通过代码来配置它:

val myActorRouter = system.actorOf(Props[MyActor].withRouter(
  RoundRobinRouter(nrOfInstances = 5)))

无论哪种方式,您最终都可以myActorRouter作为演员参考,您可以向其发送消息。在后台,Akka 系统创建了一个MyActor演员池并将消息转发给他们。路由器将自己从响应中取出,因此您无需像以前那样欺骗发送者:当路由向发送者发送消息时,它会直接返回给发送消息到路由器的参与者。

于 2015-03-02T15:48:58.807 回答