akka actor监控(monitoring)

    在Akka中生命周期监控通常指的是DeathWatch。除了父actor和子actor的关系的监控关系,每个actor可能还监视着其它任意的actor。监视actor通过接收Terminated消息来实现生命周期监控。如果没有其它的处理方式,默认的行为是抛出一个DeathPactException异常。为了能够监听Terminated消息,你需要调用ActorContext.watch(targetActorRef)。调用ActorContext.unwatch(targetActorRed)来取消对目标角色的监听。需要注意的是,Terminated消息的发送与监视actor注册的时间和被监视角色终止的时间顺序无关。例如,即使在你注册的时候目标actor已经死了,你仍然能够收到Terminated消息。当监管者不能简单的重启子actor而必须终止它们时,监视将显得非常重要。例如,actor在初始化的时候报错。在这种情况下,它应该监视这些子actor并且重启它们或者稍后再做尝试。一个常见的应用案例是,一个actor或者它的子actor在无法获得需要的外部资源时需要失败。如果是第三方通过调用system.stop(child)方法或者发送PoisonPill消息来终止子actor时,监管者也将会受到影响。 

class WatchActor extends Actor {

	val child = context.actorOf(Props.empty,"child")
 	context.watch(child)
	var lastSender = system.deadLetters

	def	receive = {
		case "kill"⇒ context.stop(child)
		lastSender = sender
		case Terminated(`child`) ⇒ lastSender !"finished"
	}
}


注意:
1,Terminated 消息的产生与注册和终止行为所发生的顺序无关。多次注册并不表示会有多个消息产生,也不保证有且只有一个这样的消息被接收到:
如果被监控的actor已经生成了消息并且已经进入了队列,在这个消息被处理之前又发生了另一次注册,则会有第二个消息进入队列,因为一个已经终止的actor注册监控器会立刻导致 Terminated 消息的发生。


2,可以使用 context.unwatch(target) 来停止对另一个actor的生存状态的监控,但很明显这不能保证不会接收到 Terminated 消息因为该消息可能已经进入了队列。


较完整的代码实例:

import akka.actor.{PoisonPill, ActorSystem, Props}
import com.typesafe.config.ConfigFactory

object DeathClient {

  def main(args: Array[String]) {

    val system = ActorSystem("DeathWatchDemo",ConfigFactory.load("localsystem.conf"))

    val parentActor = system.actorOf(Props(new ParentActor()), name="Parent")

    parentActor ! "msg from childActor"

    /**
     * 给ParentActor和childActor点时间让她们初始化完成,不然的话下面的actorSelection会获取不到actor
     */
    Thread.sleep(500)

    val childActor = system.actorSelection("/user/Parent/childActor")
    childActor ! PoisonPill

//    system.shutdown
  }
}




import akka.actor.{Terminated, Props, Actor}

class ParentActor extends Actor {

  println("ParentActor construction method start ....")

  val jason = context.actorOf(Props(new ChildActor()), name="childActor")

  /**
   * ParentActor 对ChildActor进行监控,可以监视到ChildActor的Death(收到Terminated 消息)
   */
  context.watch(jason)

  println("ParentActor construction method end ....")

  override def preStart() = {
    /**
     * 在新生成actor执行完类的构造方法后调用此方法
     */
    println("ParentActor preStart ...")
  }

  def receive = {
    case Terminated(child) => println("ParentActor watch ChildActor:{} dead",child)
    case msg : String => println("ParentActor received a message: " + msg)
  }
}



import akka.actor.Actor

class ChildActor extends Actor {

  def receive = {
    case Some(msg) => println("ChildActor some msg is : " + msg)
    case _ => println("ChildActor got a message")
  }
}




你可能感兴趣的:(akka)