Akca学習ノート:Actorライフサイクル

7224 ワード

ここで述べているライフサイクルには、preRestartやpostRestartの方法が含まれていません。私たちは、レギュレータを検討する時に彼らを説明します。
Actorの基本的なライフサイクルはとても直観的です。実際には以下の点を除いて、ActorのライフサイクルとJava servletライフサイクルを比較することができます。1、他の普通類と同じように、構造関数が必要です。2、preStart関数はその後に呼び出されます。ここでは、いくつかのリソースを初期化してからpostStopでクリアできます。3、servicingまたはreceive方法におけるメッセージ処理は圧倒的に多くの時間を占めている。簡単なActorを見てみましょう。彼はライフサイクルだけをプリントします。
package me.rerun.akkanotes.lifecycle

import akka.actor.{ActorLogging, Actor}  
import akka.event.LoggingReceive

class BasicLifecycleLoggingActor extends Actor with ActorLogging{

  log.info ("Inside BasicLifecycleLoggingActor Constructor")
  log.info (context.self.toString())
  override def preStart() ={
    log.info("Inside the preStart method of BasicLifecycleLoggingActor")
  }

  def receive = LoggingReceive{
    case "hello" => log.info ("hello")
  }

  override def postStop()={
    log.info ("Inside postStop method of BasicLifecycleLoggingActor")
  }

}
LifecycleAppleクラスはActorを初期化してメッセージを送信し、ActorSystemを閉じます。
import akka.actor.{ActorSystem, Props}

object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")

  lifecycleActor!"hello"

  //wait for a couple of seconds before shutdown
  Thread.sleep(2000)
  actorSystem.shutdown()

 }
結果
Inside BasicLifecycleLoggingActor Constructor
Actor[akka://LifecycleActorSystem/user/lifecycleActor#-2018741361]
Inside the preStart method of BasicLifecycleLoggingActor
hello
Inside postStop method of BasicLifecycleLoggingActor
Servletライフサイクルと基本的なActorの違いは何ですか?Actorの構造方法とpreStart方法は別に違いません。基本は同じです。どうして構造方法でcontext.selfをプリントアウトしますか?これはActorがServletと違って、構造方法でもActorConteetにアクセスできるからです。preStartと構造方法の境界は非常にあいまいになった。後に監督について話します。その違いをもう一回話します。もしあなたが気になるなら、まずここで紹介します。Actorが再起動する時(失敗再起動など)preStart方法を呼び出して再初期化できます。構造の方法の中で実現することができないのです。
postStopメソッドはいつ呼び出されますか?
プログラムからActorSystemがオフになった時に、postStopメソッドが呼び出されたことが分かりました。他にもいくつかの状況があります。1、ActorSystem.stop()ActorSystemまたはActorContectのstop方法を呼び出してActorを閉じることができます。
object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")

  actorSystem.stop(lifecycleActor);

  ...
  ...

}
2、ActorControtext.stop 1)、メッセージ(内部または外部を通る)
class BasicLifecycleLoggingActor extends Actor with ActorLogging{  
...
...
  def receive = LoggingReceive{
    case "hello" => log.info ("hello")
    case "stop" => context.stop(self)
  }
 object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")


  lifecycleActor!"stop"
...
...
2)、あるいは何の理由もなく自分で自分を殺す(ここは冗談です)
class BasicLifecycleLoggingActor extends Actor with ActorLogging{

  log.info ("Inside BasicLifecycleLoggingActor Constructor")
  log.info (context.self.toString())
  context.stop(self)
  ...
  ...
3、POISO NPILLは前の例では、LifecycleAppでstop付きメッセージをActor、Actorに送って、このメッセージを受けて、context.stopで自分を殺します。実は私達はPoisonPillメッセージを送ることで同じ機能を達成することができます。PoisonPillは前のstopメッセージと似ています。普通のポストに入れられて並んでいます。順番が来る時だけ処理します。
object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")

  lifecycleActor!PoisonPill
  ...
  ...
4.KILL PoisonPillを使いたくないなら、Killメッセージを送ることでターゲットActorに送ることができます。
lifecycleActor ! Kill
PoisonPillメッセージとKillメッセージの違いは小さいですが、重要です。1、PoisonPillメッセージを使ったら、すべてのWatchにTerminatedメッセージを送ります。2、Killメッセージを使ったら、宿主Actorkilled Exceptionを抛り出して、管理者のところに伝播します。  
停止フェーズ
Actorが一旦停止したら、彼もTerminatedの状態に入ります。あなたの頭の中では、停止したActorに送信されたメッセージは何が起こると思いますか?ちょっと見てみましょう。
object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")

  lifecycleActor!"hello"
  lifecycleActor!"stop"
  lifecycleActor!"hello" //Sending message to an Actor which is already stopped

}
Actor――前と同じです。
class BasicLifecycleLoggingActor extends Actor with ActorLogging{

  def receive = LoggingReceive{
    case "hello" => log.info ("hello")
    case "stop" => context.stop(self)

  }
}
出力
BasicLifecycleLoggingActor - hello

akka.actor.RepointableActorRef - Message 1 from Actor[akka://LifecycleActorSystem/deadLetters] to Actor[akka://LifecycleActorSystem/user/lifecycleActor#-569230546] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
ログからいくつかのdeadlettersを見ることができます。終了したActorに送信されたすべてのメッセージはDeadLetter Actorという内部Actorに転送されます。
  
後ろで何が起こるか気になりますか?
DeadLetter Actorは自分のメールボックスのメッセージを処理して、各メッセージを一つのDeadLetterにカプセル化してから、EventStreamに発表します。もう一つはDeadLetter ListenerというActorがこれらすべてのDeadLetterメッセージを消費して、それらを一つのログメッセージとして発表します。ここを見てください。覚えているでしょう。Akca日記の記事で、すべての日誌情報はEventStreamに掲載されます。私たちは自由に購読できます。予約者だけでもActorです。試してみましょう。この例では、私たちはEventStreamに購読し、DeadLetterメッセージをすべて傍受して、コンソールに印刷します。実は私達は多くのことをすることができます。例えば警告を生成したり、データベースに保存したり、それを使って分析したりします。
import akka.actor.ActorSystem  
import akka.actor.Props  
import akka.actor.PoisonPill  
import akka.actor.DeadLetter  
import akka.actor.Actor

object LifecycleApp extends App {

  val actorSystem = ActorSystem("LifecycleActorSystem")
  val lifecycleActor = actorSystem.actorOf(Props[BasicLifecycleLoggingActor], "lifecycleActor")

  val deadLetterListener = actorSystem.actorOf(Props[MyCustomDeadLetterListener])
  actorSystem.eventStream.subscribe(deadLetterListener, classOf[DeadLetter])

  lifecycleActor ! "hello"
  lifecycleActor ! "stop"
  lifecycleActor ! "hello"

}

class MyCustomDeadLetterListener extends Actor {  
  def receive = {
    case deadLetter: DeadLetter => println(s"FROM CUSTOM LISTENER $deadLetter")
  }
}
出力
164  [LifecycleActorSystem-akka.actor.default-dispatcher-4] INFO  BasicLifecycleLoggingActor - hello 

167  [LifecycleActorSystem-akka.actor.default-dispatcher-4] INFO  akka.actor.RepointableActorRef - Message 1 from Actor[akka://LifecycleActorSystem/deadLetters] to Actor[akka://LifecycleActorSystem/user/lifecycleActor#-782937925] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'. 

FROM CUSTOM LISTENER DeadLetter(hello,Actor[akka://LifecycleActorSystem/deadLetters],Actor[akka://LifecycleActorSystem/user/lifecycleActor#-782937925])
出典: http://www.iteblog.com/archives/1221