终止一个鞭a的akka​​演员

时间:2013-09-27 07:17:35

标签: akka

我有以下演员设置,使用Akka演员(2.10)

A -spawn-> B -spawn-> ç

A -sendWork-> B -sendWork-> ç

C -sendResults-> A(反复)

然而,在某些时候A注意到它应该改变发送到B / C的工作量,因为C发送的大量消息结果是无用的。但是,在这种情况下,C的收件箱似乎非常满,和/或C可能被阻止。

如何告诉B立即关闭C?丢失B和C的状态和消息是可以接受的,因此可以选择销毁它们并生成新的消息。

1 个答案:

答案 0 :(得分:1)

鉴于演员按照您描述的方式开始,然后以正确的方式使用stop将完成您的要求。根据文档,调用stop将同时:

1)阻止其他邮件进入邮箱(发送到deadletter)

2)获取邮箱的当前内容并将其发送到deadletter(虽然这是基于邮箱impl,但重点是它们不会被处理)

现在如果演员需要完全完成它正在处理的消息,那么它会一直停止,所以如果它被“卡住”,停止(或者任何事情)就不会解决这个问题,但我不会认为这就是你所描述的情况。

我将一些代码示例拉到一起进行演示。基本上,A会向B发送一条消息,开始向C发送工作.B会将C工作淹没,C会将该工作的结果发回给A.当A收到一定数量的回复时,它会通过停止B触发B和C的停止。当B完全停止时,它将再次重新启动该过程,最多2次,因为它自行停止。代码如下所示:

case object StartWork
case class DoWork(i:Int, a:ActorRef)
case class WorkResults(i:Int)

class ActorA extends Actor{
  import context._
  var responseCount = 0
  var restarts = 0

  def receive = startingWork

  def startingWork:Receive = {
    case sw @ StartWork =>
      val myb = actorOf(Props[ActorB])
      myb ! sw      
      become(waitingForResponses(myb))
  }

  def waitingForResponses(myb:ActorRef):Receive = {
    case WorkResults(i) =>
      println(s"Got back work results: $i")
      responseCount += 1
      if (responseCount > 200){
        println("Got too many responses, terminating children and starting again")
        watch(myb)
        stop(myb)
        become(waitingForDeath)
      }
  }

  def waitingForDeath:Receive = {
    case Terminated(ref) => 
      restarts += 1
      if (restarts <= 2){
        println("children terminated, starting work again") 
        responseCount = 0
        become(startingWork)
        self ! StartWork
      }
      else{
        println("too many restarts, stopping self")
        context.stop(self)
      }

  }
}

class ActorB extends Actor{
  import concurrent.duration._
  import context._  
  var sched:Option[Cancellable] = None

  override def postStop = {
    println("stopping b")
    sched foreach (_.cancel)
  }

  def receive = starting

  def starting:Receive = {
    case sw @ StartWork =>
      val myc = context.actorOf(Props[ActorC])
      sched = Some(context.system.scheduler.schedule(1 second, 1 second, self, "tick"))
      become(sendingWork(myc, sender))
  }

  def sendingWork(myc:ActorRef, a:ActorRef):Receive = {
    case "tick" => 
      for(j <- 1 until 1000) myc ! DoWork(j, a)

  }
}

class ActorC extends Actor{
  override def postStop = {
    println("stopping c")
  }
  def receive = {
    case DoWork(i, a) =>
      a ! WorkResults(i)      
  }
}

边缘有点粗糙,但它应该表明,从B到C的级联级联将阻止C将响应发送回A,即使它仍然在邮箱中有消息。我希望这就是你要找的东西。