Статьи

Акка Заметки — Детские Актеры и ActorPath — 6

Актеры полностью иерархичны. Независимо от актеров, которых вы создаете, ДОЛЖНО быть ребенком какого-то другого актера.

Давайте проанализируем это немного:

Путь

Скажем, мы создаем ActorRef с помощью ActorSystem.actorOf и пытаемся распечатать его path .

1
2
3
val actorSystem=ActorSystem("SupervisionActorSystem"
val actorRef=actorSystem.actorOf(Props[BasicLifecycleLoggingTeacherActor]) 
println (actorRef.path) // (prints) akka://SupervisionActorSystem/user/$a

Как видите, путь очень похож на путь к файлу в файловой системе.

  1. akka здесь исправлена, потому что все это адреса Akka Actors — больше похоже на префикс file:// или http:// (хотя протокол не имеет ничего общего).
  2. SupervisionActorSystem — это просто имя вашей ActorSystem, которую вы создали.
  3. Мы поговорим о user в следующем разделе.
  4. $a A — это имя вашего актера, которое система сгенерировала для вас. Как бы вы хотели, чтобы ваша операционная система генерировала случайные имена файлов для ваших файлов? Вы, очевидно, ненавидели бы это, потому что вы хотели бы сослаться на это имя в будущем. Итак, давайте дадим ему правильное осмысленное имя:
1
2
val actorRef=actorSystem.actorOf(Props[BasicLifecycleLoggingTeacherActor], "teacherActor"
println (actorRef.path)     // (prints) akka://SupervisionActorSystem/user/teacherActor

Вот и все. Теперь путь действительно имеет смысл.

TopLevelActor

Актеры

Подобно актерам верхнего уровня, которые мы создаем из ActorSystem, мы также можем создавать дочерних акторов из ActorContext . Фактически, сила отказоустойчивости актеров в первую очередь заключается в использовании иерархии акторов и способности родителей управлять жизнью дочерних актеров.

Предположим, у вас есть TeacherSupervisor и вы хотите создать ActorContext.actorOf как ActorContext.actorOf элемент ActorContext.actorOf вместо ActorContext.actorOf вы делаете ActorSystem.actorOf :

1
2
3
4
class TeacherSupervisor extends Actor with ActorLogging { 
  val teacherActor=context.actorOf(Props[TeacherActor], "teacherActor")
...
...

Честно говоря, в любом приложении вы будете создавать больше дочерних акторов, чем актеров верхнего уровня — это означает, что вы будете вызывать намного больше actorContext.actorOf чем actorSystem.actorOf .

TopLevelWithChild

Вы заметите, что путь дочернего актера akka://SupervisionActorSystem/user/teacherSupervisor/teacherActor , который очень похож на путь, который вы получаете при создании дочерней папки в родительской папке.

Когда вы создаете детей актеров?

Обычно вы создаете дочерних акторов, когда определенная задача состоит из подзадачи или нескольких подзадач. Вы также создаете дочерний актер, когда определенная задача, которая будет выполняться родителем, подвержена ошибкам, и вы захотите изолировать ее (чтобы в случае сбоя вы могли ее восстановить). Если между задачами нет родительских и дочерних отношений, вы НЕ создаете дочерних акторов.

Кроме того, ничто не мешает дочернему актеру создавать детей для делегирования его подзадач. Актеры и их творчество действительно дешевы, но сила, которая приходит с ними, удивительна (мы увидим это, пока будем говорить о наблюдении)

Теперь, что это за user ?

Из-за отсутствия креативности позвольте мне сравнить ActorSystem с файловой системой Unix — с папкой / root и всеми этими /etc , /usr , /bin и различными другими папками.

ActorSystem очень похожи на это. Он создает несколько Актеров высшего уровня — наиболее важными из них являются корневой Актор с путем / , пользовательский Актер с путем /user и системный Актер с путем /system . (есть также /deadLetters , представляющий DeadLetterActorRef . Мы видели это в нашем предыдущем посте )

В коде ActorSystem состоит из трех акторов (через ActorRefProvider ). Это корень для ВСЕХ Актеров, которые создаются в ActorSystem.

  1. systemGuardian actor — корень всех актеров в /system
  2. актер- guardian — корень всех актеров в /user и
  3. rootGuardian Actor — корень как systemGuardian и пользовательских userGuardian .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
/**
   * Reference to the supervisor of guardian and systemGuardian; ....
   */
  def rootGuardian: InternalActorRef
 
  /**
   * Reference to the supervisor used for all top-level user actors.
   */
  def guardian: LocalActorRef
 
  /**
   * Reference to the supervisor used for all top-level system actors.
   */
  def systemGuardian: LocalActorRef

ActorHierarchy

/ user (aka) user guardian

Любой Actor, который вы создаете в своей программе, например StudentActor или StudentActor используя метод ActorSystem actorOf будет напрямую попадать в /user . Это причина, по которой ваш teacherActor в первой части этой статьи имел путь slug /user/teacherActor .

/ system (aka) системный хранитель

Системный хранитель отключается, когда замечает, что userGuardian мертв. Имеет смысл учитывать, что если userGuardian не работает, то все бизнес-субъекты в нем также не userGuardian , и поэтому все административные субъекты также должны быть удалены.

Мы могли видеть два разных места, где создаются субъекты системы — я имею в виду актеров в иерархии /system .

  1. Как мы уже видели ранее , любое сообщение, которое вы отправляете DeadLetterActor перенаправляется в почтовый ящик внутреннего DeadLetterActor именем DeadLetterActor . Актер DeadLetter упаковывает каждое сообщение как DeadLetter и публикует его в EventStream. Еще один Actor под названием DeadLetterListener потребляет все DeadLetters и публикует это как сообщение журнала. Теперь DeadLetterListener — это системный субъект с путем /system/deadLetterListener .
  2. Помните TestEventListener который мы создали в нашей предыдущей TestEventListener для подписки на сообщения журнала в EventStream? Они тоже системные игроки. На самом деле все akka.loggers создаются как субъекты системы.
1
2
3
class TeacherTest extends TestKit(ActorSystem("UniversityMessageSystem", ConfigFactory.parseString("""akka.loggers = ["akka.testkit.TestEventListener"]"""))) 
...
...

Документация здесь говорит, что любой Actor, который сконфигурирован в файлах конфигурации и создан и развернут в ActorSystem во время его запуска, попадает под зонтик /system . Позвольте мне обновить этот пост, когда я найду что-то интересное вокруг этого

/ (иначе) хранитель корней

Как мы видели ранее, / Actor является родителем пользователя и системных опекунов.

TRIVIA

Технически, у корневого субъекта тоже есть лишний родитель. Единственная задача этого актера — отключить всю систему ActorSystem в случае сбоя корневого агента. Так как это строго не учитывается в иерархии Actor, команда Akka называет это так:

1
2
private[akka] val theOneWhoWalksTheBubblesOfSpaceTime: InternalActorRef = new MinimalActorRef {
...
Ссылка: Заметки Акки — Детские актеры и ActorPath — 6 от нашего партнера JCG Аруна Маниваннана в блоге Rerun.me .