【问题标题】:Scala and akka lifecycle.. againScala和akka生命周期..再次
【发布时间】:2013-07-14 06:50:21
【问题描述】:

所以这个问题与我的一个老问题有关:Do I need to re-use the same Akka ActorSystem or can I just create one every time I need one?

我问了一个关于演员生命周期的问题,我知道我的想法有问题,但无法正确表达。希望我现在可以:-)。

情况是这样的。我想测试依赖于其他组件和演员的演员,所以我开始在引导时间组合我的演员(我正在使用 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决定工作完成时,我的理解是它应该广播给路由的actors以关闭。此时,当另一个请求进入时,actorA 无法再向路由器发送消息,因为它的所有参与者都已死亡。

如果我没有在启动时进行设置,那么可以在我的应用程序需要时创建 actorA 及其依赖项。但这很像 DI 世界中的“新对象”。为了测试,我最终会覆盖创建演员的地方。

Scalatra 文档建议在启动时创建我的演员,所以我觉得我在这里遗漏了一些东西。任何帮助表示赞赏。

干杯,克里斯。

编辑

我对@futurechimp 和@cmbaxter 都进行了+1,因为它们似乎都有效但略有冲突。所以这是对你们俩的公开评论。

所以@cmbaxter 我认为你的建议永远不要对路由演员调用“停止”并且只是维护一个池以供所有请求使用,我是对的。还有@futurechimp,你建议让servlet根据请求实例化演员并在生命周期结束时杀死他们。对吧?

似乎每个请求都会产生更多的演员(但处置他们)。如果轮询对所有请求只有有限的集合,在这种情况下这种方法是否存在潜在瓶颈?

我想基本上,我在问我的假设是否正确,如果正确,这两种方法的优缺点是什么?

【问题讨论】:

  • 我不确定问题是什么?
  • 对不起,我真的不知道怎么问它:-)
  • 我认为 cmbaxter 和我是从不同的角度来研究它的。我是说从 Scalatra 的角度来看,没有框架规定的理由在 ScalatraBootstrap 和 Servlet 中启动 Actor。 cmbaxter 似乎提倡在启动时启动无状态 Actor(在 ScalatraBootstrap 中,如果您使用的是 Scalatra),并在每个请求的基础上启动有状态 Actor。对我来说,这似乎是一个很好的经验法则。

标签: scala akka scalatra


【解决方案1】:

实例化一个 ActorSystem 是昂贵的 - 但是实例化一个 Actor 不是。如果您只想在 ScalatraBootstrap 中实例化您的 ActorSystem,并在其他地方实例化您的 Actor,那么如果您需要这样做,那应该可以正常工作。我将与其他人交谈以确认这一点,然后更改 Scalatra's Akka Guide 中的文档以避免将来出现混淆。

【讨论】:

    【解决方案2】:

    您必须在这里问自己的一个问题是:我的演员是有状态的还是无状态的。如果是无状态的(如果可能的话,我个人更喜欢这种方法),那么它们可以是“长期存在的”,您可以在服务器启动时启动它们并让它们在服务器的生命周期内运行。当您需要从代码中的其他地方与他们交谈时,使用system.actorFor(String)system.actorSelection(String)(取决于您使用的akka​​ 版本)查找actor 并向其发送消息。如果参与者是有状态的,那么他们可能应该是“短暂的”并启动以响应个人请求。在这种情况下,您不会在服务器启动时启动它们;您只会启动ActorSystem 本身。然后,当请求进来时,您将通过system.actorOf 进行实例化,并确保在工作完成后停止ActorA,因为它是所有ActorBs 的主管,停止A 将停止所有由A 发起的Bs。

    【讨论】: