Getting Started with Actors [Akka in a Nutshell #2]

Table of contents
Reading Time: 4 minutes

Hierarchical Structure

Actors are objects which encapsulate state and behavior, they communicate by exchanging messages. We can consider an actor as a person.

Like a software development team, actors form hierarchies. In a team there is a project manager who takes requirements from client and distributes it over to different team leads. Then those team leads further distribute the tasks to other team members.Team members after finsihing their tasks, report to their team lead about the status.

Similarly, an actor might wants to split up a task into smaller tasks. For that actor creates child actors and if by any means child actor is unable to execute successfully then it will send a corresponding failure message to it’s parent where it is created from.

Actor System

An actor system manages the resources it is configured to use in order to run the actors which it contains.

The actor system as a collaborating ensemble of actors is the natural unit for managing shared facilities like scheduling services, configuration, logging, etc.

Components of Actor System

  • User Guardian Actor: User Guardian Actor is the parent of all actor we create.
  • System Guardian Actor: System Guardian Actor is the parent of all actors the akka itself creates.
  • Dead Letter Office: It is an actor just like other actors but every time a message is sent to an actor which does not exists or running then goes to the dead letter office.
  • Scheduler: It is used for scheduling tasks.

Creating an Actor with Props

Props is a configuration class to specify options for the creation of actors.

Here are some examples of how to create a Props instance:

val props1 = Props[MyActor]

val props2 = Props(new ActorWithArgs(“args”))

val prop3 = Props(classOf[ActorWithArgs], “arg”)

Note:

The recommended approach to create the actor Props is not supported for cases when the actor constructor takes value classes as arguments.

Declaring one actor within another is very dangerous and breaks actor encapsulation. Never pass an actor’s this reference into Props!

Recommended practice is defining the prop method inside the companion object.

object MyActor {

def props(num: Int): Props = Props(new MyActor(num))

}

class MyActor(num: Int) extends Actor {

def receive = {

case x: Int => sender() ! (x + num)

}

}

class MyAnotherActor extends Actor {

context.actorOf(MyActor.props(10), "my-actor")

}

Also declaring what messages an Actor can receive in the companion object of the Actor is consider to be a recomended practice.

object MyActor {

case class Greeting(from: String)

case object Bye

}

class MyActor extends Actor {

import MyActor._

def receive = {

case Greeting(greeter) => println(s”Hello $greeter”)

case Bye => println(s”Good by everyone”)

}

}

Tell vs Ask

There are two ways we can talk to an Actor:

  • Tell (!)
  • Ask (?)

Tell (!) : Fire and Forget, which means you send a message asynchronously and aren’t interested in result.
Ask (?) : Ask also send the message asynchronously but unlike Tell it receives a result in future.

object MyActor {

case class Sum(a: Int, b: Int)

}

class MyActor extends Actor {

override def receive: Receive = {

case Sum(a: Int, b: Int) => sender() ! (a + b)

case _ => sender() ! 0

}

}

object TellAndAsk extends App{

implicit val duration: Timeout = 20 seconds

val system = ActorSystem("ask-and-tell")

val myActor = system.actorOf(Props[MyActor], "my-actor")

val sum: Future[Int] = (myActor ? Sum(3,4)).asInstanceOf[Future[Int]]

println("Sum of 3 and 4 is " + Await.result(sum, Duration.Inf))

system.terminate()

}

ActorRef vs ActorSelection vs ActorPath

ActorRef is the interface for actor system and it is a reference for a single actor. When an actor stops actorRef, it starts pointing to Dead Letter Office which means if any message is send through that actor reference it will go to Dead Letter Office. Each time we create a new actor akka will create a new actor reference. We can create actor reference using actorOf method.

val system = ActorSystem(“my-actor-system”)

/*Here the actor is an actor reference*/

val actor = system.actorOf(Prop[MyActor])

Actor Path

Actors are created in a strictly hierarchical fashion. Every actor in an Actor system is given a unique name. As told earlier, every actor created has a parent either it is a user guardian or another user created actor. So path for any actor is like a file system which starts with the root (/) and then the user followed by root since all the actors that we create are children of user guardian. Let’s say we created an actor with name my-actor then path for my-actor will be:

/user/my-actor

Similarly if we create any actor from my-actor then it will be parent for our new actor and path will be like:

/user/my-actor/

Actor Selection
Actor selection is another way to represent an actor. Just like actorRef we can send message via ActorSelection but the difference is that it is created from actor path.

system.actorSelection("/user/parent/child")

ActorSelection stays valid even after an actor dies.

Checkout Source Code for Actor Selection demonstrating actor selection stays valid even after Actor Dies.

 https://gist.github.com/PKOfficial/a9d56def7379dc9ee51f850adf854f26


So that’s it for now checkout our already covered topics

In our further blog series, we’ll cover the following topics :

  • Akka Persistence
  • Exploring Akka Networking
  • How to test an Actor?
  • A dive into Akka Streams

Co-Author: 

References:

http://akka.io/docs/


KNOLDUS-advt-sticker

Written by 

I am from India and developing Scala Microservices :)

3 thoughts on “Getting Started with Actors [Akka in a Nutshell #2]4 min read

Comments are closed.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading