在Akka创建演员的成本是多少?

Mar*_*ila 27 performance scala akka

考虑一个我正在实现使用Akka处理传入任务的系统的场景.我有一个主要角色接收任务并将它们分派给处理任务的一些工作者.

我的第一直觉是通过让调度员为每个传入任务创建一个actor来实现这一点.在worker actor处理任务后,它将停止.

这对我来说似乎是最干净的解决方案,因为它坚持"一个任务,一个角色"的原则.另一个解决方案是重用actor - 但这涉及清理和一些池管理的额外复杂性.

我知道阿卡的演员很便宜.但我想知道是否存在与重复创建和删除演员相关的固有成本.是否存在与Akka用于记录演员的数据结构相关的隐藏成本?

负载应该是每秒数十或数百个任务的量级 - 将其视为生产网络服务器,每个请求创建一个actor.

当然,正确的答案在于根据传入负载的类型对系统进行分析和微调.但我想知道是否有人可以根据自己的经验告诉我一些事情?

后期编辑:

我应该提供有关手头任务的更多细节:

  • 只有N个活动任务可以在某个时刻运行.正如@drexin指出的那样 - 使用路由器很容易解决这个问题.但是,任务的执行不是简单的运行,而是完成事物的类型.
  • 任务可能需要来自其他参与者或服务的信息,因此可能需要等待并入睡.通过这样做,他们释放了一个执行槽.这个插槽可以由另一个现在有机会运行的等待角色扮演.您可以对在一个CPU上调度进程的方式进行类比.
  • 每个工作者都需要保持关于任务执行的一些状态.

注意:我很欣赏我的问题的替代解决方案,我一定会考虑它们.但是,我还要回答关于在Akka中密集创建和删除演员的主要问题.

dre*_*xin 19

您不应该为每个请求创建一个actor,您应该使用路由器将消息分派给动态数量的actor.这就是路由器的用途.阅读这部分文档以获取更多信息:http://doc.akka.io/docs/akka/2.0.4/scala/routing.html

编辑:

创建顶级actor(system.actorOf)是很昂贵的,因为每个顶级actor都会初始化一个错误内核,而且这些内核很昂贵.创建儿童演员(演员内部context.actorOf)的方式更便宜.

但我仍然建议你重新考虑一下,因为根据创建和删除演员的频率,你也会对GC施加压力.

EDIT2:

最重要的是,演员不是线程!因此,即使您创建了1M actor,它们也只会在池中运行尽可能多的线程.因此,根据配置中的吞吐量设置,每个actor将在线程再次释放到池之前处理n个消息.

请注意,阻止线程(包括休眠)不会将其返回池中!


par*_*tic 8

在创建后立即收到一条消息并在发送结果后立即死亡的演员可以被未来取代.期货比演员更轻量级.

完成后,您可以使用它pipeTo来接收未来的结果.例如,在你的actor中启动计算:

def receive = {
  case t: Task => future { executeTask( t ) }.pipeTo(self)
  case r: Result => processTheResult(r)
}
Run Code Online (Sandbox Code Playgroud)

executeTask你的职能在哪里Task取回一个Result.

但是,我会通过路由器重用池中的actor,如@drexin中所述.