我正在尝试使用akka群集(http://doc.akka.io/docs/akka/2.3.9/scala/cluster-usage.html)将Akka应用程序从单层重构为多层结构。在应用程序中有一些具有参数化默认构造函数的actor,例如
class MyActor(someParam: boolean = true) extends Actor {
def receive = { /* message handling here... */ }
}
我现在正在尝试创建一个通用路由器actor,它将路由到具有特定节点的节点。群集配置基于akka站点上的示例工作,我可以在1个角色中创建一个路由到另一个角色的actor的路由器:
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得出这个,但似乎无法正确 - 这种方法不允许我为actor创建道具。我见过How to instantiate an instance of type represented by type parameter in Scala,我认为类型信息正在丢失(类型擦除)。
如何将actor类传递给路由器代理以允许路由器初始化?
这是我在编译期间获得的错误,同时初始化路由器:
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]
适用于无参数的actor,但Props(classOf[T])
会丢失该类型。
答案 0 :(得分:1)
您实际上不必为路由器定义另一个类,您可以通过配置文件完成所有操作:
val myActorRouter = system.actorOf(Props[MyActor]
.withRouter(FromConfig())
,"workerRouter")
在您的application.conf文件中定义“workerRouter”,如下所示:
akka.actor.deployment {
/workerRouter {
router = round-robin
nr-of-instances = 5
}
}
如果你有一个非常简单的配置,你也可以通过代码配置它:
val myActorRouter = system.actorOf(Props[MyActor].withRouter(
RoundRobinRouter(nrOfInstances = 5)))
无论哪种方式,你最终都会以myActorRouter
作为演员参考,你可以发送消息。在后台,Akka系统创建了一个MyActor
个演员池,并将消息转发给他们。路由器将自己从响应中取出,因此您不需要像完成任务一样欺骗发送方:当一个routee向发送方发送消息时,它会直接返回发送消息到路由器的actor。