The Actor model is the core concept of Akka, so the organization structure of Actor in Akka is also very important. This paper mainly introduces the Actor system in Akka.

The Actor system

Actor, as an object that encapsulates state and behavior, always needs a system to organize and manage them uniformly. In Akka, it is ActorSystem. In fact, it is very easy to understand, just like a company, every employee can be regarded as an Actor, they have their own positions and responsibilities, but we need to gather employees together. Unified management and assignment of tasks, so we need a corresponding system for management, just like the ActorSystem here for Actor management.

Main functions of ActorSystem

ActorSystem has the following three functions:

  • Managing scheduling services
  • Configuring Related Parameters
  • logging

1. Manage the scheduling service

The essence of ActorSystem is to divide tasks until a task is small enough to be processed completely, and then entrust it to Actor for processing. Therefore, one of the most core functions of ActorSystem is to manage and schedule the operation of the entire system. It is just like the manager of a company who needs to make the development plan of the whole company. It is also necessary to assign the work to the corresponding staff to complete, to ensure the correct operation of the whole company. In fact, this also reflects the divide and rule in software design, and the core idea in Actor is the same.

ActorSystem model example:

ActorSystem model example

Above is a simple development collaboration process, and I think this example should clearly express the organization of actors in Akka, but not only that. The main features are as follows:

  • The organization of actors in Akka is a tree structure
  • Every Actor has a parent, which may or may not have children
  • Parent actors assign resources, tasks to their children, and manage their lifestates (policing and monitoring)

Actors systems often have thousands of actors, and using a tree structure to organize and manage actors is a good fit.

And Akka is distributed by nature. You can send messages to a remote Actor, but you need to know where the Actor is, and you’ll find that tree structures are very useful for determining the path of an Actor (like Linux file storage). So I think actors are perfect for organizing with trees.

2. Create an environment based on the configuration

A good ActorSystem must have some configuration information, such as log management used, log levels printed in different environments, interceptors, mailboxes, etc. Akka uses the Typesafe library, which is a very powerful library, and I will write a follow-up article, so please look forward to it.

Here is a simple example of how ActorSystem generates the Actor environment based on the configuration file:

1. First of all, we will print the log level of the system according to the default configuration and build Akka environment. Please refer to my last article: Akka series (1) : Introduction to Akka and Actor model

val actorSystem = ActorSystem("robot-system")
println(s"the ActorSystem logLevel is ${actorSystem.settings.LogLevel}")Copy the code

Running results:

the ActorSystem logLevel is INFOCopy the code

You can see that the default log output level of ActorSystem is INFO.

2. Now we configure the log output level in application.conf:

akka {

# Log level used by the configured loggers (see "loggers") as soon
# as they have been started; before that, see "stdout-loglevel"
# Options: OFF.ERROR.WARNING.INFO.DEBUG
loglevel = "DEBUG"
}Copy the code

Running results:

[DEBUG] [03/26/2017 12:07:12.434] [main] [EventStream(akka://robot-system)] logger log1-Logging$DefaultLoggerStarted [DEBUG] [03/26/2017 12:07:12.436] [main] [EventStream(akka://robot-system)] Default Loggers started the ActorSystemlogLevel is DEBUGCopy the code

You can see that the log output level of ActorSystem has changed to DEBUG.

This is mainly to demonstrate that ActorSystem can load the corresponding environment according to the content of the configuration file, and apply to the entire ActorSystem, which is very convenient for us to configure the ActorSystem environment.

3. Log function

Akka has a high fault tolerance mechanism, which undoubtedly requires perfect logging to enable actors to make timely recovery strategies after errors, such as persistence in Akka. Some of these effects may be mentioned later in a follow-up chapter.

Actor references, paths, and addresses

Knowing Actor references, paths, and addresses is a lot easier with the knowledge above.

When is an Actor reference?

An Actor reference is a subclass of ActorRef. Each Actor has a unique ActorRef. An Actor reference can be regarded as an Actor proxy. Sending a message to an Actor actually sends the message to the corresponding reference of the Actor, which then posts the message to the mailbox of the specific Actor. Therefore, ActorRef plays a very important role in the entire Actor system.

How do I get an Actor reference?

  • Create Actor directly
  • Find actors that already exist
1. Obtain ActorRef

Those of you who read my last article are familiar with this method of obtaining Actor references. Here I will demonstrate several methods of obtaining ActorRef:

Consider the following scenario: the boss senses an opportunity in the market and is ready to start a new project. He communicates the requirements to the manager, who assigns suitable employees to work according to the corresponding needs.

This example is very simple, now let’s simulate the scenario:

1. First let’s create some messages:

trait Message {
  val content: String
}
case class Business(content: String) extends Message {}
case class Meeting(content: String) extends Message {}
case class Confirm(content: String, actorPath: ActorPath) extends Message {}
case class DoAction(content: String) extends Message {}
case class Done(content: String) extends Message {}Copy the code

2. Let’s create a company. Here is the embodiment of ActorSystem:

val actorSystem = ActorSystem("company-system") // First we create a company
Actorsystem.actorof (actorSystem.actorof); // Create an Actor to get ActorRef
val bossActor = actorSystem.actorOf(Props[BossActor]."boss") // The company has a Boss
bossActor ! Business("Fitness industry has great prospects") // It is observed from the market that the fitness industry will have a great prospectCopy the code

3. Here we will create several roles, such as Boss above, Manager, Worker here, let’s have a look:

class BossActor extends Actor {
  val log = Logging(context.system, this)
  implicit val askTimeout = Timeout(5 seconds)
  import context.dispatcher
  var taskCount = 0
  def receive: Receive = {
    case b: Business =>
      log.info("I must to do some thing,go,go,go!")
      println(self.path.address)
      // Another way to create an Actor to get an ActorRef is to use actorContext.actorof
      val managerActors = (1 to 3).map(i =>
        context.actorOf(Props[ManagerActor].s"manager${i}")) // Here we call 3 directors
      // Tell them to hold a meeting to discuss big plans
      managerActors foreach {
        _ ? Meeting("Meeting to discuss big plans") map {
          case c: Confirm= >// Why can we know the parent Actor?
            // Those familiar with tree structures should know that each node has only one parent (except the root node)
            log.info(c.actorPath.parent.toString)
            // Get ActorRef from existing Actor path
            // where c.actorPath is the absolute path, you can also get the corresponding ActorRef based on the relative path
            val manager = context.actorSelection(c.actorPath)
            manager ! DoAction("Do thing")}}case d: Done => {
      taskCount += 1
      if (taskCount == 3) {
        log.info("the project is done, we will earn much money")
        context.system.terminate()
      }
    }
  }
}
class ManagerActor extends Actor {
  val log = Logging(context.system, this)
  def receive: Receive = {
    case m: Meeting =>
      sender() ! Confirm("I have receive command", self.path)
    case d: DoAction= >val workerActor = context.actorOf(Props[WorkerActor]."worker")
      workerActor forward d
  }
}

class WorkerActor extends Actor {
  val log = Logging(context.system, this)
  def receive: Receive = {
    case d: DoAction =>
      log.info("I have receive task")
      sender() ! Done("I hava done work")}}Copy the code

It may not be easy to understand just by looking at this code, but here’s a flow chart to help you understand it:

Program flow chart:

Program flow chart

See the above flow chart should have some understanding of the program, too much explanation I will not explain here, you can see the notes, or download the source code to run. Source link

There are two main points of knowledge:

  • Create an Actor to get an ActorRef in two ways
  • Get the ActorRef from the Actor path

The previous knowledge point should be more clear, specifically say the second.

2.Actor path and address

Those of you familiar with Unix-like systems should be familiar with the concept of a path. Each ActorSystem has a root guardian, denoted by /. Under the root guardian there is an Actor named User, which is the parent Actor of all system.actorof () creations.

/user/boss

Address as the name suggests is the Actor’s location, why do you want to have the address, a concept that is that Akka powerful concept, all things are in the Akka is designed to work in a distributed environment, so we can send any position of the Actor messages (if you have to know where it is), the role of this address to emerge, First we can find the location of the Actor according to the address, and then according to the path to find the specific Actor, such as our example program bossActor, its complete location is

akka://company-system/user/boss

You can see that its address is

akka://company-system

Akka is purely local. The default location of remote Actor in Akka usually starts with akka.tcp or akka.udp. Of course, you can also use third-party plug-ins.

In general, this article mainly explains the ActorSystem infrastructure, related configuration, as well as Actor reference, path and address and other basic knowledge points, which is actually very helpful to understand how the whole Actor system works. The blogger also wrote for a long time, trying to write a popular and easy to understand. Hope to get your support, the next article is going to write about Actor supervision and monitoring and its life cycle.