所以这个问题与我的一个旧问题有关:Do I need to re-use the same Akka ActorSystem or can I just create one every time I need one?
我问了一个关于演员生命周期的问题,我知道我脑子里有些不对劲,但是无法正确地说出来。希望我现在可以: - )。
这是情况。我想测试与其他组件和actor有依赖关系的actor,所以我在bootstrap时间编写我的actor(我正在使用scalatra但是你引导你的应用程序)。因此,我有这样的事情:
trait DependencyComponent
{
val dependency : Dependency
}
trait ActorComponentA extends Actor with DependencyComponent {
val actorB : ActorRef
}
trait ActorComponentB extends Actor with DependencyComponent
好的,现在我可以通过扩展特性和提供模拟依赖来测试我的演员,一切都很好。我可以像这样引导我的应用程序:
val system = ActorSystem()
val actorA = system.actorOf(Props[DefaultActorA])
class DefaultActorB extends ActorComponentB {
val dependency = new RealDependency()
}
class DefaultActorA extends ActorComponentA {
val dependency = new RealDependency()
val actorB = context.actorOf(Props[DefaultActorB]).withRouter(RoundRobinRouter(nrOfInstances = 100)))
}
很酷,我很高兴:-),现在我可以在我的应用程序中使用actorSystem和actorA,它有一个100个actorB路由来传递工作。因此,当actorA决定完成工作时,我的理解是它应该向路由的演员广播以关闭。此时,当另一个请求进入时,actorA不再向路由器发送消息,因为它的所有actor都已死亡。
如果我没有在启动时设置它,那么可以在我的应用程序中需要时创建actorA及其依赖项。但这非常像DI世界中的“新事物”。为了测试我最终会覆盖创建演员的地方。
Scalatra docs建议在开机时创建我的演员,所以我觉得我在这里缺少某些东西。任何帮助表示赞赏。
干杯,克里斯。
我同时给@futurechimp和@cmbaxter +1,因为这些似乎都有效,但有点矛盾。所以这是对你们两个人的公开评论。
所以@cmbaxter我认为你的建议永远不会在路由的演员身上调用'停止'而只是维护它们的池以供所有请求使用。并且@futurechimp,你建议让servlet按照请求实例化actor并在生命周期结束时杀死它们。正确?
似乎每个请求会产生更多的actor(但处理它们)。如果民意调查对所有请求只有一个有限的集合,那么这种方法可能存在瓶颈?
我想基本上,我在问我的假设是否正确,如果是这样,这两种方法的优点和缺点是什么?
答案 0 :(得分:2)
实例化ActorSystem很昂贵 - 但实例化Actor不是。如果您只想在ScalatraBootstrap中实例化您的ActorSystem,并在其他地方实例化您的Actors,那么如果您需要这样做,这应该可以正常工作。我会与其他人交谈以确认这一点,然后更改Scalatra's Akka Guide中的文档,以避免将来出现混淆。
答案 1 :(得分:1)
你在这里要问的一个问题是:我的演员是有状态还是无国籍。如果无状态(我希望在可能的情况下我个人更喜欢这种方法),那么它们可以“长寿”,并且您可以在服务器启动时启动它们并使其在服务器生命周期内保持运行。当您需要从代码中的其他位置与他们交谈时,请使用system.actorFor(String)
或system.actorSelection(String)
(取决于您使用的akka的版本)来查找actor并向其发送消息。如果演员将成为有状态的,那么他们可能应该是“短命的”并且在响应个人请求时启动。在这种情况下,服务器启动时不会启动它们;你只会启动ActorSystem
本身。然后,当请求进入时,您将通过system.actorOf
进行实例化,并确保在完成工作时停止ActorA
,因为它是所有ActorB
的主管并停止A
将停止B
开始的所有A
。