检查actor的终止并避免向该actor发送消息

时间:2016-09-15 21:53:46

标签: scala akka

我想避免向被终止的演员发送死信,并避免向该演员发送消息

class PingActor extends Actor with ActorLogging {
  import PingActor._

  var counter = 0
  var sendMessages = true
  val pongActor = context.actorOf(PongActor.props, "pongActor")
  context.watch(pongActor)

  def receive = {
    case Terminated(pong) =>
      sendMessages = false


    case Initialize =>
        println("In PingActor - starting ping-pong")
      pongActor ! PingMessage("ping")
    case PongActor.PongMessage(text) =>
      println("In PingActor - received message: {}", text)
      counter += 1
      if (counter == 10 ) context.system.shutdown()
      else {
        context.actorSelection(pongActor.path) ! PingMessage("ping")
      }
  } 
}
class PongActor extends Actor with ActorLogging {
  import PongActor._
  var counter = 0

  def receive = {
    case PingActor.PingMessage(text) => 
      println(s"In PongActor - received message: $text counter = $counter \n reply with pong message")

      if (counter < 5) {
        counter = counter + 1
      }
      else
        {
          println("Oh crap , bye bye ")
          context.stop(self)
        }
      sender() ! PongMessage("pong")

  }

actorSelection没有按预期工作,ping发送的最后一条消息仍然以死信结束:

  

[INFO] [09/16/2016 00:47:46.237]   [MyActorSystem-akka.actor.default-调度-4]   [akka:// MyActorSystem / user / pingActor / pongActor]消息   [com.example.PingActor $ PingMessage]来自   演员[akka:// MyActorSystem / user / pingActor#1697177867]来   演员[akka:// MyActorSystem / user / pingActor / pongActor#524615423]不是   交付。 [1]遇到死信。可以转换此日志记录   关闭或调整配置设置'akka.log-dead-letters'   和'akka.log-dead-letters-during-shutdown'。

2 个答案:

答案 0 :(得分:1)

根据演员的异步性质,我不认为你可以在Terminated上传播。我想一旦你收到DeadLetter消息,你就确定演员已经死了。但是,当actor死亡时,邮箱中可能仍有少量消息等待处理。你可以做的是让另一个演员在def __str__(self): return self.student_subject + " " + Student.last_name 频道上听,并且如果该演员获得了一个意图传递给其他演员的消息就行动。

答案 1 :(得分:0)

@hveiga回答的另一种选择可能是:

仅在从pongActor收到pong后发送下一个ping消息。通过这种方式,您可以控制是否应该发送它们。但是如果负荷很高,那将是一个很高的瓶颈。

var buffer = 0;
def receive = {
    case Terminated(pong) =>
      sendMessages = false

    case Initialize =>
      if(buffer == 0){
          self ! SendMsg
          buffer = buffer+1;
       } else buffer = buffer +1;
    case SendMsg => 
          println("In PingActor - starting ping-pong")
          pongActor ! PingMessage("ping")

    case PongActor.PongMessage(text) =>
         buffer = buffer -1;
         if(buffer > 1) self ! SendMsg
         .....
  } 

除了手动处理,您还可以stash。因此,当您从pongActor

收到Initialize时,后续的PongMessage不会被处理

更好的设计可能是:你每隔5秒左右继续发送消息并继续检查响应。如果PongActor没有在该持续时间内回复,则可能意味着它已经死亡。你会得到一个没有回复的消息列表。因此,问责制得到了解决。