Актеры полностью иерархичны. Независимо от актеров, которых вы создаете, ДОЛЖНО быть ребенком какого-то другого актера.
Давайте проанализируем это немного:
Путь
Скажем, мы создаем 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 |
Как видите, путь очень похож на путь к файлу в файловой системе.
-
akkaздесь исправлена, потому что все это адреса Akka Actors — больше похоже на префиксfile://илиhttp://(хотя протокол не имеет ничего общего). -
SupervisionActorSystem— это просто имя вашей ActorSystem, которую вы создали. - Мы поговорим о
userв следующем разделе. -
$aA — это имя вашего актера, которое система сгенерировала для вас. Как бы вы хотели, чтобы ваша операционная система генерировала случайные имена файлов для ваших файлов? Вы, очевидно, ненавидели бы это, потому что вы хотели бы сослаться на это имя в будущем. Итак, давайте дадим ему правильное осмысленное имя:
|
1
2
|
val actorRef=actorSystem.actorOf(Props[BasicLifecycleLoggingTeacherActor], "teacherActor") println (actorRef.path) // (prints) akka://SupervisionActorSystem/user/teacherActor |
Вот и все. Теперь путь действительно имеет смысл.
Актеры
Подобно актерам верхнего уровня, которые мы создаем из 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 .
Вы заметите, что путь дочернего актера akka://SupervisionActorSystem/user/teacherSupervisor/teacherActor , который очень похож на путь, который вы получаете при создании дочерней папки в родительской папке.
Когда вы создаете детей актеров?
Обычно вы создаете дочерних акторов, когда определенная задача состоит из подзадачи или нескольких подзадач. Вы также создаете дочерний актер, когда определенная задача, которая будет выполняться родителем, подвержена ошибкам, и вы захотите изолировать ее (чтобы в случае сбоя вы могли ее восстановить). Если между задачами нет родительских и дочерних отношений, вы НЕ создаете дочерних акторов.
Кроме того, ничто не мешает дочернему актеру создавать детей для делегирования его подзадач. Актеры и их творчество действительно дешевы, но сила, которая приходит с ними, удивительна (мы увидим это, пока будем говорить о наблюдении)
Теперь, что это за user ?
Из-за отсутствия креативности позвольте мне сравнить ActorSystem с файловой системой Unix — с папкой / root и всеми этими /etc , /usr , /bin и различными другими папками.
ActorSystem очень похожи на это. Он создает несколько Актеров высшего уровня — наиболее важными из них являются корневой Актор с путем / , пользовательский Актер с путем /user и системный Актер с путем /system . (есть также /deadLetters , представляющий DeadLetterActorRef . Мы видели это в нашем предыдущем посте )
В коде ActorSystem состоит из трех акторов (через ActorRefProvider ). Это корень для ВСЕХ Актеров, которые создаются в ActorSystem.
-
systemGuardianactor — корень всех актеров в/system - актер-
guardian— корень всех актеров в/userи -
rootGuardianActor — корень как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 |
/ user (aka) user guardian
Любой Actor, который вы создаете в своей программе, например StudentActor или StudentActor используя метод ActorSystem actorOf будет напрямую попадать в /user . Это причина, по которой ваш teacherActor в первой части этой статьи имел путь slug /user/teacherActor .
/ system (aka) системный хранитель
Системный хранитель отключается, когда замечает, что userGuardian мертв. Имеет смысл учитывать, что если userGuardian не работает, то все бизнес-субъекты в нем также не userGuardian , и поэтому все административные субъекты также должны быть удалены.
Мы могли видеть два разных места, где создаются субъекты системы — я имею в виду актеров в иерархии /system .
- Как мы уже видели ранее , любое сообщение, которое вы отправляете
DeadLetterActorперенаправляется в почтовый ящик внутреннегоDeadLetterActorименемDeadLetterActor. Актер DeadLetter упаковывает каждое сообщение какDeadLetterи публикует его в EventStream. Еще один Actor под названиемDeadLetterListenerпотребляет все DeadLetters и публикует это как сообщение журнала. Теперь DeadLetterListener — это системный субъект с путем/system/deadLetterListener. - Помните
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 . |


