【问题标题】:Actor good practice?演员的好习惯?
【发布时间】:2013-12-11 06:32:26
【问题描述】:

我有一个使用 scala 运行的 akka 演员系统。现在我需要并行配置多个设备,所以我有一个 Manager 角色来管理所有这些配置任务。为了实际配置它们,他将为每个配置生成一个 Worker 演员,以便它们同时或并行运行。现在Worker actor 在配置过程中并不需要从 manager 接收消息,他只需要做他的事情,然后向Manager 报告他已经完成了。

现在的问题是,我是在 Worker 的构造函数中传递指令和 ManagerActorRef,还是创建它,然后向它发送类似 Do(action: => Unit) 的消息,然后它会回复完成后到sender?是否有惯例如何做到这一点,或者被认为是一种好的做法?

编辑:正如 Vladimir Matveev 提醒我的那样,对 Manager 的引用不是问题,因为通过 context.parent 中的层次结构已经知道它。剩下的问题是如何将工作传递给Worker

【问题讨论】:

  • 如果Manager 直接生成worker,则不需要将Manager 引用传递给它们。工人可以使用context.parent访问ManagerActorRef
  • @VladimirMatveev 哦,是的,那是真的。但是他们应该做的工作呢?如果我将来使用context.scheduler.schedule... 生成,context.parent 仍然是Manager 吗?我认为应该是因为它是一个闭包,但我不确定。
  • 如果你在一个actor中使用context来生成子actor,无论你在这个actor中使用context的什么地方,它们都会以这个actor作为父actor。这很合乎逻辑,因为正如您所说,context 变量刚刚关闭,但它仍然是相同的context

标签: scala coding-style akka


【解决方案1】:

你是对的,工作应该通过消息传递给工人。因为这是与演员交流的最安全的方式。它还使您能够在 Actor 前面使用调度程序将分配的工作分配给多个工作人员。

为了清楚起见,这里有一个简短的例子:

import akka.actor.Actor
import akka.actor.Props

case class Start()
case class Finished()
case class Do(action: () => Unit)

class Manager extends Actor {

  override def preStart() =
    self ! Start()

  def receive = {
    case Start() =>
      val workers = context.actorOf(
        Props[Worker].withRouter(RoundRobinRouter(nrOfInstances = 5)))
      context.system.scheduler.schedule(5 seconds, 5 seconds, workers, Do(() => 1 * 1))

    case Finished() =>
      println("A worker finished work.")
  }
}

class Worker extends Actor {
  def receive = {
    case Do(f) =>
      f()
      sender ! Finished()
  }
}

经理启动后,它将创建 5 个工作人员,并每 5 秒向他们发送一些工作。工人将执行工作并在完成后报告。您可以使用sender(始终向工作的发布者报告)或context.parent(始终向经理报告)报告已完成的工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多