Статьи

Акка Заметки: детские актеры и актерская дорожка

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

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

Путь

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

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имя вашего актера, которое система сгенерировала для вас. Как бы вы хотели, чтобы ваша операционная система генерировала случайные имена файлов для ваших файлов? Вы, очевидно, ненавидели бы это, потому что вы хотели бы сослаться на это имя в будущем. Итак, давайте дадим ему правильное осмысленное имя:
val actorRef=actorSystem.actorOf(Props[BasicLifecycleLoggingTeacherActor], "teacherActor")  
println (actorRef.path)     // (prints) akka://SupervisionActorSystem/user/teacherActor

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

Актер высшего уровня

Актеры

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

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

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

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

Актер для родителей и детей

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

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

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

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

Теперь, что это userна пути?

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

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

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

  1. systemGuardian актер — корень всех актеров под /system
  2. guardianактер — корень всех актеров /userи
  3. rootGuardianАктер — корень systemGuardianи userGuardianактеров.
  /**
   * 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

Корневая система и опекуны пользователей

/ user (aka) user guardian

Любой актер , который вы создаете в своей программе , таких как StudentActorили с TeacherActorпомощью ActorSystemactorOfметод будет непосредственно подпадать под /user. Вот почему у вас teacherActorв первой части этой статьи был слаг-путь /user/teacherActor.

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

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

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

  1. Как мы видели ранее , любое сообщение, которое вы отправляете действующему субъекту, перенаправляется в почтовый ящик внутреннего вызываемого субъекта DeadLetterActor. DeadLetter Actor упаковывает каждое сообщение как a DeadLetterи публикует его в EventStream. Другой вызванный Actor DeadLetterListenerпотребляет все DeadLetters и публикует это как сообщение журнала. Теперь DeadLetterListener — системный актер с путем /system/deadLetterListener.

  2. Помните , TestEventListenerчто мы создали в предыдущей записи-до подписки на журнал сообщений в EventStream? Они тоже системные игроки. Фактически, все akka.loggersони созданы как субъекты Системы.

class TeacherTest extends TestKit(ActorSystem("UniversityMessageSystem", ConfigFactory.parseString("""akka.loggers = ["akka.testkit.TestEventListener"]""")))  
...
...

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

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

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


TRIVIA

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

  private[akka] val theOneWhoWalksTheBubblesOfSpaceTime: InternalActorRef = new MinimalActorRef {
...