角色是完全分层的。 无论演员,你创建必须有一些其他演员的孩子。
让我们分析一下:
路径
假设我们使用ActorSystem.actorOf
创建一个ActorRef,然后尝试打印它的path
。
val actorSystem=ActorSystem("SupervisionActorSystem")
val actorRef=actorSystem.actorOf(Props[BasicLifecycleLoggingTeacherActor])
println (actorRef.path) // (prints) akka://SupervisionActorSystem/user/$a
如您所见,路径看起来与文件系统中的文件路径非常相似。
- 这里的
akka
是固定的,因为所有这些都是Akka Actor的地址–更像是file://
或http://
前缀(尽管与协议无关)。 -
SupervisionActorSystem
只是您创建的ActorSystem的名称。 - 我们将在下一节中讨论
user
。 -
$a
是系统为您生成的Actor的名称。 如果您的操作系统为文件生成了随机文件名,您希望如何? 您显然会讨厌它,因为您将来想引用该名称。 因此,我们给它起一个适当的有意义的名称:
val actorRef=actorSystem.actorOf(Props[BasicLifecycleLoggingTeacherActor], "teacherActor")
println (actorRef.path) // (prints) akka://SupervisionActorSystem/user/teacherActor
而已。 现在,该路径实际上是有意义的。
儿童演员
与我们在ActorSystem中创建的顶级actor相似,我们也可以在ActorContext
创建子actor。 实际上,Actor的容错能力主要在于利用Actor的层次结构和父母管理孩子Actor的能力。
假设您有一个TeacherSupervisor
并且您想创建一个TeacherActor
作为Supervisor的子代,则执行ActorContext.actorOf
而不是ActorSystem.actorOf
:
class TeacherSupervisor extends Actor with ActorLogging {
val teacherActor=context.actorOf(Props[TeacherActor], "teacherActor")
...
...
坦率地说,在任何应用中,您将创建一大堆儿童演员比顶级的演员-这意味着你将调用了很多actorContext.actorOf
比actorSystem.actorOf
。
您会注意到子actor的路径是akka://SupervisionActorSystem/user/teacherSupervisor/teacherActor
,与在父文件夹中创建子文件夹时获得的路径非常相似。
您何时创建儿童演员?
通常,当特定任务由一个子任务或多个子任务组成时,您将创建子参与者。 当要由父级执行的特定任务容易出错并且您希望隔离它时,您还将创建一个子actor(这样,如果失败,则可以恢复)。 如果任务之间没有父子关系,则不要创建子actor。
而且,没有什么可以阻止子角色创建子任务来委派子任务。 演员及其创造物确实很便宜,但是其带来的力量却是惊人的(我们在谈论监督时会看到这一点)。
现在,该路径中的那个
由于缺乏创造力,让我将ActorSystem
与Unix文件系统进行比较-带有/
根文件夹以及所有/etc
, /usr
, /bin
和其他各种文件夹。
ActorSystem很像那样。 它创建了几个顶级演员-最重要的是根演员与路径/
,与路径的用户演员/user
以及与路径的系统演员/system
。 (也有一个/deadLetters
代表DeadLetterActorRef
。我们在上 /deadLetters
中看到了这一点)
在代码方面,ActorSystem在其中组成了三个Actor(通过ActorRefProvider )。 这些是在ActorSystem下创建的所有Actor的根。
-
systemGuardian
actor –/system
下所有actor的根 -
guardian
–在/user
和 -
rootGuardian
Actor –systemGuardian
和userGuardian
actor的根。
/**
* 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(又名)用户监护人
您在程序中使用ActorSystem
的actorOf
方法创建的任何Actor(例如StudentActor
或TeacherActor
都将直接位于/user
之下。 这就是在本文第一部分中您的teacherActor
具有路径slug /user/teacherActor
。
/ system(aka)系统守护者
当发现userGuardian
已死时,系统守护程序会自行关闭。 考虑到userGuardian
是否已关闭,则其下的所有业务角色也都关闭了,因此所有管理角色也都必须关闭。
我们可以看到创建系统参与者的两个不同的地方–我的意思是/system
层次结构下的参与者。
- 就像我们前面看到的 ,发送给终止的Actor的任何消息都会转发到内部Actor的名为
DeadLetterActor
的邮箱。 DeadLetter Actor将每个消息包装为DeadLetter
并将其发布到EventStream。 另一个名为DeadLetterListener
Actor会使用所有DeadLetter,并将其作为日志消息发布。 现在,DeadLetterListener是具有路径/system/deadLetterListener
。 - 还记得我们在上一篇
TestEventListener
中创建的TestEventListener
,用于订阅EventStream中的日志消息吗? 他们也是系统参与者。 实际上,所有akka.loggers
都是作为系统参与者创建的。
class TeacherTest extends TestKit(ActorSystem("UniversityMessageSystem", ConfigFactory.parseString("""akka.loggers = ["akka.testkit.TestEventListener"]""")))
...
...
此处的文档说,在配置文件中配置并在启动时创建并部署到ActorSystem中的任何Actor都位于/system
伞下。 当我发现与此有关的有趣内容时,请让我更新此帖子
/(aka)根监护人
如前所述, /
Actor是用户和系统监护人的父级。
琐事
从技术上讲,根演员也有多余的父母。 该Actor的唯一工作是在根actor发生故障时关闭整个ActorSystem。 由于严格不在Actor层次结构内,因此Akka团队将其称为:
private[akka] val theOneWhoWalksTheBubblesOfSpaceTime: InternalActorRef = new MinimalActorRef {
...
翻译自: https://www.javacodegeeks.com/2014/10/akka-notes-child-actors-and-actorpath-6.html