"AKKA Official Document Translation" Part I.: Actor architecture

Source: Internet
Author: User
Tags stdin
First part: Actor Architecture

Akka version 2.5.8
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Akka provides you with some basic functionality for creating an actor system, and has implemented the underlying code necessary to control basic behavior. To understand this, let's take a look at the relationship between the actor role you created and the management role created internally by Akka, and the way the actor's life cycle and failure is handled. hierarchy of Akka actors

The actors in Akka always belonged to their parents. Usually you create an actor by calling Context.actorof (). In this way, a new actor is added to the existing actor tree, and the actor's creator becomes the actor's parent actor. You may ask, who is the parent actor of the first actor you created?

As the following illustration shows, all actors have a common parent, called user Guardian. You can create a new actor instance that belongs to it by calling System.actorof (). As we described in the QuickStart guide, creating an actor returns a reference to a valid URL, so if we create an actor named Someactor by calling System.actorof (..., "Someactor"), its reference will contain the path /user/someactor.

In fact, before you invoke the code that you created the actor, Akka has created three actors in the system. These built-in actor names contain guardian, as they govern all sub-actors under their respective paths. Guardian actors include:

/The so-called Root guardian. This is the father of all actors in the system, and it is the last to be stopped when the system is terminated.

/user This is the father of all user-created actors. Don't be fooled by the user name, he has no relationship with the end user, and is not related to user handling. All actors that you create using the Akka Library will start with/user/
/system System Guardian

In the Hello World example, we've seen how to use System.actorof () to create an actor under the/user path. Although it is only the most advanced actor in the user-created hierarchy, we call it the top actor. In your actorsystem, you usually have only one (or very few) top actors. We create a new non-top actor, the child actor, in the existing actor by calling Context.actorof (). The method signature of Context.actorof () is the same as system.actorof ().

The simplest way to view the actor hierarchy is to print an instance of Actorref. In this little experiment, we created an actor, printed its reference, created a child actor for him, and printed a reference to its child actor. We start with the Hello World project and if you haven't downloaded it, please download the QuickStart project from Lightbend Tech hub.

In your Hello World project, navigate to the location of the Com.lightbend.akka.sample package, where you create a new Scala file Actorhierarchyexperiments.scala. Copy and paste the following code into this new file. Save the file and run the SBT "Runmain com.lightbend.akka.sample.ActorHierarchyExperiments" and observe the output.

Package com.lightbend.akka.sample

Import akka.actor.{ Actor, Props, Actorsystem}
import Scala.io.StdIn

class Printmyactorrefactor extends Actor {
  override Def receive:receive = {case
    "PrintIt" ⇒
      val secondref = context.actorof (Props.empty, "Second-actor")
      println ( S "Second: $secondRef")
  }
}

object Actorhierarchyexperiments extends App {
  val system = Actorsystem (" Testsystem ")

  val firstref = System.actorof (Props[printmyactorrefactor]," First-actor ")
  println (S" First: $ Firstref ")
  Firstref! "PrintIt"

  println (">>> Press ENTER to exit <<<")
  try Stdin.readline ()
  finally System.terminate ()
}

Notice how you send a message to the first actor to get it to work. We use the parent class reference to send the message: Firstref! "PrintIt". When the program runs, the output information contains a reference to the first actor and a reference to the child actor created in PrintIt. Your output should look like this:

FIRST:ACTOR[AKKA://TESTSYSTEM/USER/FIRST-ACTOR#1053618476]

SECOND:ACTOR[AKKA://TESTSYSTEM/USER/FIRST-ACTOR/SECOND-ACTOR#-1544706041]

Note the reference structure:

All two paths start with akka://testsystem/, and all actor references are valid URLs. AKKA://is the Protocol field.

Next, as in the World Wide Web, the URL is the identity of a system. In this example, the name of the system is Testsystem, which can also be named as any name. If remote communication between multiple systems is turned on, the URL contains the host name so that other systems can find it on the network.

Because the second actor refers to a path that contains/first-actor/, it indicates that it is the child actor of the first actor.

The last paragraph of the actor reference, #1053618476 and #-1544706041 is the unique identifier UID of an actor, and you can ignore its existence in most scenarios.

Now that you seem to understand the hierarchy of the actor system, you might think: why do we need this hierarchy? What's he doing with it?

A very important function of the hierarchy is to safely manage the actor's life cycle, and then let's think about how to use it to write good code. the life cycle of the actor

The actor exists after it is created and disappears when the user request is closed. When the actor is closed, all its sub-actors are closed recursively. This feature greatly simplifies our resource cleanup efforts and prevents resource leaks (sockets or files, etc.). In fact, in the low-level multithreaded programming, we often underestimate the complexity of the various concurrent resource lifecycle management.

In order to close the actor, we recommend calling Context.stop (self) from within the actor, which is often placed in a user-defined end-of-message response, or invoked after the actor has done its job. Stopping other actors is technically permissible and can be achieved by calling Context.stop (Actorref). But stopping an actor in this way is a bad habit , but you can send the actor a poisonpill or a custom close message to close it.

Akka's actor provides a very pair of lifecycle APIs that you can overload when implementing actors. The most commonly used are Prestart () and Poststop ().

Prestart () is called after the actor is started and before it processes the first message

Poststop () will be called before the actor is closed, and after it, the actor will not process any more messages.

Let's simply experiment with how to use Prestart () and poststop () lifecycle hooks to observe the behavior of the actor when it is closed. First, add the following two actor classes to your project:

Class StartStopActor1 extends Actor {
  override Def prestart (): Unit = {
    println ("first started")
    Context.actorof (Props[startstopactor2], "second")
  }
  override Def poststop (): Unit = println ("First stopped")

  override Def receive:receive = {case
    ' stop ' ⇒context.stop (self)
  }
}

class StartStopActor2 Extends Actor {
  override Def prestart (): unit = println ("second started")
  override Def poststop (): unit = Printl N ("second stopped")

  //Actor.emptybehavior is a useful placeholder
  //in which we do not want to use this Actor to process any information that is used by the
  override Def receive: Receive = Actor.emptybehavior
}

Create a main class (main) as before, responsible for creating actors and sending them a "stop" message after that.

Val first = System.actorof (Props[startstopactor1], "first") First
! "Stop"

You can use SBT again to start the program, and the resulting output should look like this:

First started

Second started

Second stopped

First stopped

When we stop firstactor, it shuts down its sub-actor:second before it is closed. This order is strictly enforced, and all poststop () hooks of the child actors will be called before their parent actorpoststop () call.

The actor Life cycle section of the Akka Reference manual provides detailed information about the entire lifecycle hook. Failure Handling

The parent actor and the child actor are kept in touch throughout the declaration cycle. When an actor fails (throws an exception or pops an unhandled exception in receive), he is temporarily suspended. As mentioned earlier, the failure message is passed to the parent actor, which is then determined by the parent actor to handle the exception generated by the child actor. In this way, the parent actor is the supervisor of the child actor, and the default policing strategy is to stop and restart the child actor. If you do not modify the default regulatory policy, all failures will cause the actor to be restarted.

Let's test the default regulatory strategy in a simple experiment. As before, add the following classes to your project.

Class Supervisingactor extends Actor {
  val child = Context.actorof (Props[supervisedactor], "Supervised-actor")

  override Def receive:receive = {case
    "Failchild" ⇒child! "Fail"
  }
}

class Supervisedactor extends Actor {
  override Def prestart (): Unit = println ("supervised  Actor started ")
  override Def poststop (): Unit = println (" supervised actor stopped ")

  override Def receive:receive = {case
    ' fail ' ⇒
      println ("supervised actor fails now")
      throw new Exception ("I failed!")
  }
}

and run in Mian with the following code:

Val supervisingactor = System.actorof (Props[supervisingactor], "Supervising-actor")
Supervisingactor! "Failchild"

You should see output similar to the following:

Supervised actor started supervised actor fails now supervised actor stopped supervised actor started [ERROR] [03/29/2017 10:47:14.150] [testsystem-akka.actor.default-dispatcher-2] [akka://testsystem/user/supervising-actor/
Supervised-actor] I failed!
        Java.lang.exception:i failed! At tutorial_1.supervisedactor$ $anonfun $receive$4.applyorelse (actorhierarchyexperiments.scala:57) at Akka.actor.Ac Tor$class.aroundreceive (actor.scala:513) at Tutorial_1.SupervisedActor.aroundReceive ( actorhierarchyexperiments.scala:47) at Akka.actor.ActorCell.receiveMessage (actorcell.scala:519) at Akka.ac Tor. Actorcell.invoke (actorcell.scala:488) at Akka.dispatch.Mailbox.processMailbox (mailbox.scala:257) at AKKA.D Ispatch. Mailbox.run (mailbox.scala:224) at Akka.dispatch.Mailbox.exec (mailbox.scala:234) at Akka.dispatch.forkjoin. Forkjointask.doexec (forkjointask.java:260) at Akka.dispatch.forkjoin.forkjoinpool$workqueue.runtask (ForkJoinPool.java:1339) at Akka.dispatch.forkjoin.ForkJoinPool.runWorker (forkjoinpool.java:1979) at Akka.dispatch.fo Rkjoin. Forkjoinworkerthread.run (forkjoinworkerthread.java:107)

We saw that after the actor failed, the supervised actor was immediately stopped and restarted, and we saw a log of this exception being processed. In the test, we use Prestart () and poststop () hooks, which can be called before and after the actor is restarted, so we cannot use it to distinguish whether the actor was first initiated or restarted. Restarting the actor is correct in most cases, and restarting allows the actor to revert to a known correct state, which is the clean state at startup. What really happens internally is that the Prerestart () and Postrestart () methods are called, and if they are not overloaded, they call Poststop () and Prestart () respectively, and you can try overloading these methods to see the output change.

If you are already impatient, you can get more in-depth details on the supervision reference page. Summary

We have learned how Akka manages actors, actors are hierarchical, and the parent actor supervises their sub-actors and handles the exception of child actors. We saw how to create a very simple actor and sub-actor. Next, we'll use communication modeling to apply this knowledge to our instances to get information from the device actor. After that, we'll learn how to manage actors in a group.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.