何时在Akka中使用Ask模式

时间:2015-05-21 20:07:22

标签: scala akka

我开始学习Akka,在许多官方示例中,我看到使用request-response模式实现了tell。即在工人完成工作后,他将结果作为新消息发送给发件人。例如,在this Pi近似官方教程中展示了如何设计应用程序,其中Master向工作人员发送一些工作,然后等待结果作为另一条消息。

主码:

def receive = {
  case Calculate ⇒
    for (i ← 0 until nrOfMessages) workerRouter ! Work(i * nrOfElements, nrOfElements)
  case Result(value) ⇒
    pi += value
    nrOfResults += 1
    if (nrOfResults == nrOfMessages) {
      // Send the result to the listener
      listener ! PiApproximation(pi, duration = (System.currentTimeMillis - start).millis)
      // Stops this actor and all its supervised children
      context.stop(self)
    }
}

工人代码:

 def receive = {
    case Work(start, nrOfElements) ⇒
      sender ! Result(calculatePiFor(start, nrOfElements)) // perform the work
  }

但我想知道为什么这个例子没有使用ask模式?在这里使用ask模式有什么问题?

如果可以在这里使用询问模式,那么我还有另一个问题:如何在工作完成后停止所有工人演员?

  1. 我的工作人员应该向自己发送PoisonPill消息吗?
  2. 或者应该是演员Broadcast(PoisonPill)
  3. 还有其他更优雅的方式?

1 个答案:

答案 0 :(得分:7)

使用ask API集成actor时,

Future非常有用,但它们会引入一些开销。此外,Future完成不是通过actor的邮箱进行的,而是安排在与邮箱使用的线程分开的线程上,这意味着在actor内部接收未来的完成会引入进行多线程协调的需要。 / p>

与此同时,如果您使用tell发送给工作人员并让tell sender作为响应,则通信将始终通过邮箱通道正常流动。

此外,如果演员通过receive进入而不是通过receive和其他人作为ask消息的完成进入,则更容易辨别演员所处理的输入

要解决您PoisonPill个问题,答案可能是取决于。您可以选择 worker-per-message 方法,在这种情况下,工作人员应该自杀。相反,如果您使用工作池,则可以让主管负责上下调整该池,让它发送PoisonPill或让工作人员闲置时间,再次自杀。