(Обратите внимание, что эта запись жизненного цикла не распространяется на preRestart или postRestart . Мы поговорим о них, когда будем обсуждать надзор)
Основной жизненный цикл актера очень интуитивно понятен. Фактически вы можете сравнить базовый жизненный цикл Actor с жизненным циклом Java-сервлета с одним специальным отличием.
- Как и в любом другом обычном классе, у нас есть конструктор
- Метод
preStartснова. Здесь вы можете инициализировать ресурсы, которые вы хотите очистить вpostStop - «Обслуживание» или обработка сообщений методом
receiveзанимает большую часть времени, и это происходит между ними.
Давайте посмотрим на простого актера, который печатает жизненный цикл.
Тупой актер жизненного цикла
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package me.rerun.akkanotes.lifecycleimport akka.actor.{ActorLogging, Actor} import akka.event.LoggingReceiveclass 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") }} |
Приложение
LifecycleApp просто инициирует, отправляет сообщение Actor и завершает работу ActorSystem.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
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() } |
Выход
|
1
2
3
4
5
6
7
8
9
|
Inside BasicLifecycleLoggingActor ConstructorActor[akka://LifecycleActorSystem/user/lifecycleActor#-2018741361]Inside the preStart method of BasicLifecycleLoggingActorhelloInside postStop method of BasicLifecycleLoggingActor |
В чем особая разница между сервлетами и базовым жизненным циклом актера?
Нет никакой разницы между конструктором и предварительным запуском в жизненном цикле Actor — более или менее.
Причина, по которой я напечатал context.self в конструкторе, заключается в следующем — в отличие от сервлетов, Actors имеют доступ к ActorContext даже внутри конструктора. Разница между preStart и конструктором становится очень тонкой. Мы еще вернемся к разнице, пока будем говорить о надзоре, но если вам любопытно, можно вызвать предварительный preStart когда перезапуск актера (в случае сбоя) можно контролировать. С конструктором это невозможно.
Когда вызывается postStop?
Как мы видели из программы, postStop когда ActorSystem выключается. Есть несколько других случаев, когда обратный вызов тоже вызывается.
1. ActorSystem.stop ()
Мы могли бы остановить Actor, используя метод stop ActorSystem и ActorContext
|
01
02
03
04
05
06
07
08
09
10
11
|
object LifecycleApp extends App{ val actorSystem=ActorSystem("LifecycleActorSystem") val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor") actorSystem.stop(lifecycleActor); ... ...} |
2. ActorContext.stop
1) Либо посредством сообщения (извне или передачи сообщения себе)
|
1
2
3
4
5
6
7
|
class BasicLifecycleLoggingActor extends Actor with ActorLogging{ ...... def receive = LoggingReceive{ case "hello" => log.info ("hello") case "stop" => context.stop(self) } |
и
|
1
2
3
4
5
6
7
8
9
|
object LifecycleApp extends App{ val actorSystem=ActorSystem("LifecycleActorSystem") val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor") lifecycleActor!"stop"...... |
2) ИЛИ убить себя без причины
(это просто для развлечения. Ни один актер с амбициями не сделает этого)
|
1
2
3
4
5
6
7
|
class BasicLifecycleLoggingActor extends Actor with ActorLogging{ log.info ("Inside BasicLifecycleLoggingActor Constructor") log.info (context.self.toString()) context.stop(self) ... ... |
3. PoisonPill
В предыдущем примере мы передали сообщение с именем stop из LifecycleApp в Actor. Актер получил это сообщение и покончил с собой, используя context.stop . Мы могли бы достичь того же, передав сообщение PoisonPill целевому субъекту . Обратите внимание, что сообщение PoisonPill , как и предыдущее сообщение об остановке, ставится в очередь в обычном почтовом ящике и будет обрабатываться при его появлении.
|
1
2
3
4
5
6
7
8
|
object LifecycleApp extends App{ val actorSystem=ActorSystem("LifecycleActorSystem") val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor") lifecycleActor!PoisonPill ... ... |
TRIVIA
Что я имею в виду обычный почтовый ящик? Также есть «специальный» почтовый ящик? Ага. Там есть. И мы поговорим об этом, когда будем говорить об этом, когда будем обсуждать надзор и system сообщения.
прекращение
Как только Актер остановлен, говорят, что он входит в Terminated состояние. Непосредственный вопрос, который возникнет у вас на уме: что произойдет с сообщениями, которые отправляются действующему субъекту?
Давайте посмотрим, что:
Приложение
|
01
02
03
04
05
06
07
08
09
10
|
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} |
Актер — Как и прежде
|
1
2
3
4
5
6
7
8
|
class BasicLifecycleLoggingActor extends Actor with ActorLogging{ def receive = LoggingReceive{ case "hello" => log.info ("hello") case "stop" => context.stop(self) }} |
Выход
|
1
2
3
|
BasicLifecycleLoggingActor - hello akka.actor.RepointableActorRef - Message 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 . Любое сообщение, которое вы отправляете прекращенному действующему субъекту, пересылается в почтовый ящик внутреннего действующего субъекта с именем DeadLetterActor .
Любопытно, что произойдет дальше?
DeadLetter Actor обрабатывает сообщения в своем почтовом ящике, упаковывает каждое сообщение как DeadLetter и публикует его в EventStream .
Еще один Actor под названием DeadLetterListener потребляет все DeadLetter и публикует это как сообщение журнала. Проверьте это.
Помните, когда мы говорили о ведении журнала , мы видели, что все сообщения журнала публикуются в EventStream и что мы можем подписаться на это EventStream — просто подписчик также должен быть актером. Давайте попробуем это сейчас.
В нашем примере мы подпишемся на EventStream, следим за всеми сообщениями DeadLetter и будем печатать на консоль (так много для творчества ?? !!). Честно говоря, мы можем делать что угодно, генерируя оповещения, сохраняя их в базе данных или даже добавляя аналитику.
ПОДПИСКА НА DEADLETTERS В EVENTSTREAM
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
import akka.actor.ActorSystem import akka.actor.Props import akka.actor.PoisonPill import akka.actor.DeadLetter import akka.actor.Actorobject 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") }} |
Выход
|
1
2
3
4
5
|
164 [LifecycleActorSystem-akka.actor.default-dispatcher-4] INFO BasicLifecycleLoggingActor - hello 167 [LifecycleActorSystem-akka.actor.default-dispatcher-4] INFO akka.actor.RepointableActorRef - Message 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]) |
| Ссылка: | Akka Notes — Actor Lifecycle — Basic — 5 от нашего партнера JCG Аруна Маниваннана в блоге Rerun.me . |