Akca学習ノート:Actorライフサイクル
7224 ワード
ここで述べているライフサイクルには、preRestartやpostRestartの方法が含まれていません。私たちは、レギュレータを検討する時に彼らを説明します。
Actorの基本的なライフサイクルはとても直観的です。実際には以下の点を除いて、ActorのライフサイクルとJava servletライフサイクルを比較することができます。1、他の普通類と同じように、構造関数が必要です。2、preStart関数はその後に呼び出されます。ここでは、いくつかのリソースを初期化してからpostStopでクリアできます。3、servicingまたはreceive方法におけるメッセージ処理は圧倒的に多くの時間を占めている。簡単なActorを見てみましょう。彼はライフサイクルだけをプリントします。
postStopメソッドはいつ呼び出されますか?
プログラムからActorSystemがオフになった時に、postStopメソッドが呼び出されたことが分かりました。他にもいくつかの状況があります。1、ActorSystem.stop()ActorSystemまたはActorContectのstop方法を呼び出してActorを閉じることができます。
停止フェーズ
Actorが一旦停止したら、彼もTerminatedの状態に入ります。あなたの頭の中では、停止したActorに送信されたメッセージは何が起こると思いますか?ちょっと見てみましょう。
後ろで何が起こるか気になりますか?
DeadLetter Actorは自分のメールボックスのメッセージを処理して、各メッセージを一つのDeadLetterにカプセル化してから、EventStreamに発表します。もう一つはDeadLetter ListenerというActorがこれらすべてのDeadLetterメッセージを消費して、それらを一つのログメッセージとして発表します。ここを見てください。覚えているでしょう。Akca日記の記事で、すべての日誌情報はEventStreamに掲載されます。私たちは自由に購読できます。予約者だけでもActorです。試してみましょう。この例では、私たちはEventStreamに購読し、DeadLetterメッセージをすべて傍受して、コンソールに印刷します。実は私達は多くのことをすることができます。例えば警告を生成したり、データベースに保存したり、それを使って分析したりします。
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