Akka学习笔记:子Actor和Actor路径

Actors完全是分层结构,任何你所创建的Actor必定是其他Actor的子Actor。让我们来分析一下:

路径

  假如我们用ActorSystem.actorOf方法创建了一个ActorRef,并尝试打印出它的路径

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是系统给你的Actor生成的名字。你是否会喜欢操作系统随便给你文件产生名字呢?你肯定会讨厌,因为以后你可能会引用这个名字,所以让我们给它取一个有意义的名字吧。

val actorRef=actorSystem.actorOf(Props[BasicLifecycleLoggingTeacherActor], "teacherActor")  
println (actorRef.path)     // (prints) akka://SupervisionActorSystem/user/teacherActor

好了,现在这个路径看起来有意义多了。


如果想及时了解Spark、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号:iteblog_hadoop

子Actor

  就像我们用ActorSystem创建出顶级的actor一样,我们可以用ActorContext创建出子actor。事实上,Actor强大的错误容错能力就依赖于Actor的分层结构,并且使得父Actor拥有管理子Actor生命的能力。
  假如你有个TeacherSupervisor Actor,你想用它创建一个子Actor TeacherActor。你得使用ActorContext.actorOf方法,而不是 ActorSystem.actorOf:

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

坦白地说,在任何应用程序中,你会创建大量的子Actor而非顶层的Actor-这也意味着你调用actorContext.actorOf的次数比actorSystem.actorOf要多的多。


如果想及时了解Spark、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号:iteblog_hadoop

  你可能会注意到,子Actor的路径是akka://SupervisionActorSystem/user/teacherSupervisor/teacherActor,这跟你在父目录里面创建子目录看起来非常像。

  

什么时候你会创建子Actor

  当一项特定的任务由一个子任务或多个的子任务组成的时候,你会创建子Actor。亦或是有些任务在父Actor执行时候比较容易出现错误,这时候你想创建子Actor来隔离父Actor(这样即使它失败了,你可以恢复)。当你的Tasks之间没有父子关系的时候,你最好不要创建子Actor。
  同样的,你无法阻止子Actor继续创建子Actor来委派自己的子任务。Actor以及创建Actor是非常廉价的,但它所带来的意义却非常深远(后面介绍到监督的时候会继续讲到这点)。

  

那么路径中的user是干嘛用的?

  由于缺乏创意(For lack of a creativity),我们这里把ActorSystem比作Unix file system-带有一个/作为根目录,/etc, /usr, /bin和其他目录。
  ActorSystem和这个很像。它会创建一些顶层Actors-包括了最重要的带有/路径的顶级Actor;带有/user路径的user Actor以及带有/system路径的System Actor(其中还有带有/deadLetters路径的DeadLetterActorRef,这在前面一篇文章中已经介绍了),
  从代码角度看,ActorSystem内部由三个Actor组成(通过ActorRefProvider实现),他们是通过ActorSystem创建的Actor的根
  1、systemGuardian actor �C 是所有属于/system目录下的根Actor
  2、guardian actor �C 是所有属于/user目录下的根Actor
  3、rootGuardian Actor -它是systemGuardian Actor和guardian 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 (aka) user guardian
  所有你用ActorSystem的actorOf方法创建的Actor都直接在/user目录下,比如StudentActor和TeacherActor。这也就是为什么在前面的teacherActor中包含/user/teacherActor路径
  /system (aka) system guardian
  当system guardian检测到userGuardian停掉了,它会关闭掉自己。这是因为如果userGuardian停掉了,它下面的所有业务Actor也会停掉,所以所有的监管Actor也应该停掉。
  一共存在两种不同创建System Actors的方法,我这里说的Actor属于/system继承体系。
  1、如前一篇文章所述,任何发送给已终止Actor的消息都会转发到一个叫DeadLetterActor的内部Actor的邮箱里。DeadLetterActor会将每条消息封装成一个DeadLetter消息并发布到EventStream中去。另一个叫DeadLetterListener的Actor会去消费这些DeadLetter消息并将它们作为日志打印出来。这里的DeadLetterListener就是一个System Actor,它的路径是 /system/deadLetterListener。
  2、还记得我们前面的创建的TestEventListener?它也是System Actor。事实上,所有的akka.loggers都是作为System Actor来创建的。

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

 / (aka) root guardian
  我们前面说了,/ Actor是 user guardians和system guardians的根.

  从技术上来讲,根Actor也有父Actor,它只负责做一件事情,就是当根Actor崩溃的时候去关掉整个ActorSystem。严格来说,由于在Actor结构中并没有提到它,因此Akka团队把它叫作:

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


你可能感兴趣的:(akka)