5. Akka Actor life cycle

Actor life cycle

The life cycle of an Actor is embodied and controlled by Hooks. We can rewrite related Hooks to achieve fine-grained control of each link of the Actor life cycle. The sequence relationship of various Hooks is as follows:
(img-6m9LXV8f-1610516371587)(/Users/lipan/app/typora-pic/image-20210113125834499.png)]

  • prestart():Called after the constructor, it will not be executed when restarting.
  • postStop():Called before restarting, it will not be executed when restarting abnormally.
  • preRestart(reason, message):Save the current state before the actor restarts abnormally. By default, postStop() is called.
  • postRestart():After the actor restarts abnormally, the state saved before the restart is restored. By default, preStart() is called.
    Insert picture description here

Sample code

ParentActor.scala: Receive messages sent from Main.scala, initialize or control ChildActor.

package com.lp.akka.notes.lifecycle

import akka.actor.{
    
    Actor, ActorLogging, Props, ReceiveTimeout}

/**
 * @author li.pan
 * @version 1.0.0
 * @Description 父Actor
 * @createTime 2021年01月13日 13:04:00
 */
class ParentActor extends Actor with ActorLogging {
    
    
  println("start pActor ")

  def receive = {
    
    
    case "test" => log.info("received test")
    case ("newChild", name: String) => context.actorOf(Props[ChildActor], name)
    case ("stop", name: String) => {
    
    
      val child = context.actorFor(self.path + "/" + name);
      context.stop(child)
    }
    case ReceiveTimeout => throw new RuntimeException("received timeout"); // 每隔超时时间没收到消息就抛出异常
    case "suicide" =>
    case x: Any => log.info("received unknown message :" + x)
  }

  /**
   * 在 actor 实例化后执行,重启时不会执行
   */
  override def preStart {
    
    
    println("actor:" + self.path + ", parent preStart ")
  }

  /**
   * 在 actor 正常终止后执行,异常重启时不会执行。
   */
  override def postStop {
    
    
    println("actor:" + self.path + ",parent postStop .")
  }

  /**
   * 在 actor 异常重启前保存状态
   */
  override def preRestart(reason: Throwable, message: Option[Any]) {
    
    
    println("actor:" + self.path + ", preRestart parent, reason:" + reason + ", message:" + message)
  }

  /**
   * 在 actor 异常重启后恢复状态
   */
  override def postRestart(reason: Throwable) {
    
    
    println("actor:" + self.path + ", postRestart parent, reason:" + reason)
  }
}

ChildActor.scala: Child Actor, controlled by ParentActor.

package com.lp.akka.notes.lifecycle

import akka.actor.Actor

/**
 * @author li.pan
 * @version 1.0.0
 * @Description 子 Actor
 * @createTime 2021年01月13日 13:03:00
 */
class ChildActor extends Actor {
    
    

  override def receive() = {
    
    
    case "abc" => println("get abc string ")
    case "exception" => throw new NullPointerException()
    case _ => println("children cann't handle unknown message")
  }

  override def preStart {
    
    
    println("actor:" + self.path + ",child preStart .")
  }

  override def postStop {
    
    
    println("actor:" + self.path + ",child postStop .")
  }

  override def preRestart(reason: Throwable, message: Option[Any]) {
    
    
    println("actor:" + self.path + ",preRestart child, reason:" + reason + ", message:" + message)
  }

  override def postRestart(reason: Throwable) {
    
    
    println("actor:" + self.path + ",postRestart child, reason:" + reason)
  }
}

LifeCycleMainApp: Initialize and send messages to the Actor.

package com.lp.akka.notes.lifecycle

import akka.actor.{
    
    ActorSystem, Kill, Props}

/**
 * @author li.pan
 * @version 1.0.0
 * @Description 主类
 * @createTime 2021年01月13日 13:05:00
 */
object LifeCycleMainApp extends App {
    
    

  // 构建Actor系统
  val system = ActorSystem("lpLocalSys")

  // 通过Props方式创建父Actor
  val pActor = system.actorOf(Props[ParentActor], name = "pActor")

  pActor ! ("newChild", "child-1")
  pActor ! ("newChild", "child-2")
  pActor ! "test"

  val parent = system.actorSelection("akka://lpLocalSys/user/pActor")
  parent ! "test"
  //    parent ! ("stop", "child-2")

  val child2 = system.actorSelection("akka://lpLocalSys/user/pActor/child-2")
  child2 ! Kill // 杀死 child2
  //    child2 ! "exception"
  Thread.sleep(5000) // 等待 child2  被杀死
  pActor ! ("newChild", "child-2")
  //    Thread.sleep(5000)
  //    myActor ! ("newChild", "child-2")
}
                                                                             

Operation result:
Insert picture description here
In LifeCycleMainApp, if the unequal child-2 is killed, creating an actor with the same name will cause the parent actor named myactor to be abnormal, causing it to restart. According to the supervision strategy of Akka Actor, it will also restart it. Child Actor, so child-1 and child-2 will also be restarted, the output is as follows
Insert picture description here

It can be seen from the output that the parent Actor first calls preRestart, then is instantiated, then calls postRestart, and finally restarts its child Actor. The child Actor also follows the above steps.

references

  • "Akka Introduction and Practice"
  • https://coderbee.net/index.php/akka/20140814/1000
  • https://www.jianshu.com/p/16de393ec5b4

Follow the Akkaofficial account and reply to receive the "Akka Introduction and Practice" book.
Follow the official account and 数据工匠记focus on the offline and real-time technical dry goods in the big data field to share regularly! Personal website www.lllpan.top
Insert picture description here

Guess you like

Origin blog.csdn.net/lp284558195/article/details/112560703