首页 文章

了解崩溃时的akka actor默认行为

提问于
浏览
1

actor的默认行为是restart . 为了更好地理解,我创建了两个actor并导致重启:

class PingActor extends Actor with ActorLogging {
  import PingActor._
  override def postRestart(reason: Throwable): Unit = {
    log.info(s"RESTARTING")
    super.postRestart(reason)
  }
  var counter = 0
  val pongActor = context.actorOf(PongActor.props, "pongActor")
  def receive = {
    case Initialize => 
      pongActor ! PingMessage("ping")   
    case PongActor.PongMessage(text) =>
      log.info("In PingActor - received message: {}", text)
      counter += 1
      if (counter == 3) {
         log.info("FIN")
        context.system.shutdown()
      }
      if (counter == 2) {
        sender() ! PingMessage("ping")
        throw new IllegalArgumentException("Aooch")

      }
      else sender() ! PingMessage("ping")
  } 
}
object PingActor {
  val props = Props[PingActor]
  case object Initialize
  case class PingMessage(text: String)
}

class PongActor extends Actor with ActorLogging {
  import PongActor._
  def receive = {
    case PingActor.PingMessage(text) => 
      log.info("In PongActor - received message: {}", text)
      sender() ! PongMessage("pong")
  }
}

object PongActor {
  val props = Props[PongActor]
  case class PongMessage(text: String)
}

所以 PingActor 在崩溃之前发送消息,并且当Ping actor重新启动时 PongActor 回复它接受消息但发送者( PongActor )不可用 . 我确实在deadLetters中看到了这一行

[INFO] [MyActorSystem-akka.actor.default-dispatcher-4] [akka:// MyActorSystem / user / pingActor / pongActor]来自Actor的消息[com.example.PingActor $ PingMessage] [akka:// MyActorSystem / user / pingActor#-1362690296]到演员[akka:// MyActorSystem / user / pingActor / pongActor#1725419686]未送达 . [1]遇到死信 . 可以使用配置设置'akka.log-dead-letters'和'akka.log-dead-letters-during-shutdown'关闭或调整此日志记录 .

why the sender that sent the message prior to the crash is not available ? is there a way to overcome it ?

1 回答

  • 0

    正如documentation所述,重新启动actor时的默认行为是停止该actor的所有子节点 . 这就是重启后 sender 消息转为死信的原因 . 您需要覆盖默认行为并在 preStart() 挂钩中设置子项的初始化(即 PongActor ) . 另外,删除对 super.postRestart(reason) 的调用 .

    class PingActor extends Actor with ActorLogging {
      import PingActor._
    
      override def preStart(): Unit = {
        pongActor = Option(context.actorOf(PongActor.props, "pongActor"))
      }
    
      override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
        log.info("Don't stop the children")
        postStop()
      }
    
      override def postRestart(reason: Throwable): Unit = {
        log.info("RESTARTING")
      }
    
      var counter = 0
      var pongActor: Option[ActorRef] = None
    
      def receive = {
        case Initialize => 
          pongActor.foreach(_ ! PingMessage("ping"))
        case PongActor.PongMessage(text) =>
          ...
      } 
    }
    

    进行以上更改会产生以下输出:

    In PongActor - received message: ping
    In PingActor - received message: pong
    In PongActor - received message: ping
    In PingActor - received message: pong
    In PongActor - received message: ping
    Don't stop the children
    RESTARTING
    In PingActor - received message: pong
    In PongActor - received message: ping
    In PingActor - received message: pong
    In PongActor - received message: ping
    Don't stop the children
    RESTARTING
    In PingActor - received message: pong
    In PongActor - received message: ping
    In PingActor - received message: pong
    In PongActor - received message: ping
    Don't stop the children
    RESTARTING
    In PingActor - received message: pong
    In PongActor - received message: ping
    ...
    

    有关重新启动的更多信息,请参见第一个链接here .

相关问题