Working with Akka Actors


Overview

I am going to explain Akka actor model with a simple example fetching weather data from Yahoo, I am going to use akka scala API.

What is an Actor?

According to Webster dictionary an Actor is – one who acts – doer  or  one that takes part in any affair

What is Akka?

Akka is a toolkit and runtime for building highly concurrent,distributed, and resilient
message-driven applications on the JVM.

What is an Actor Model?

Akka has the concept of Actors, which provide an ideal model for thinking about highly concurrent and scalable systems.Actor model is a design pattern for writing concurrent and scalable code that runs on distributed systems.

Why Actor Model?

Multi-threaded programming runs multiple copies of your application code in their own threads and then synchronizing access to any shared objects. While it’s a complex issue, multi-threaded programming has three major faults:

  • Shared objects – protected by synchronized block or method but blocking
  • Deadlock – first thread tries to access synchronized block of second thread, while second thread tries to access synchronized block from first thread resulting in deadlock
  • Scalability – managing threads on multiple JVMs.

While Actor Model is not new and long exist in Haskell and Erlang. Akka run-time makes it fairly straightforward to write actor based applications.

Actor Model, Why Now?

Lot happened in last 20 years from mid-1990s to current date – not only its possible to scale up (at high-price) but we can scale out.

past_present.png

Actor model allows to write scalable software applications in distributed environment without pulling your hairs.

Inside Actor Model

 

actormodel (2)

Let’s understand how it works

  1. Actor System: is a glue that wires Actors, ActorRefs, Dispatchers, and Mailboxes together. Programmers use the ActorSystem to configure the desired implementation of each of these components. It creates and initializes actors.
  2. Next, actor creation process is initiated by sender (usually itself) which invokes actorOf() on ActorSystem creates reference of Actor object. At this time Actor may not be created/initiated. ActorRef acts as a proxy to Actor object and provides interface to communicate with Actor.
  3. Sendor Actor (Caller – in this case “actor itself from step 2”) uses  ! (bang operator known as tell message pattern – “fire-and-forget”, e.g. send a message asynchronously and return immediately.) to tell the receiving Actor about the event (Hi Actor, Can you please process this event?)
  4. ActorRef in response dispatches the event on MessageDispatcher (you can configure ActorSystem to use specific dispatcher by invoking withDispatcher)
  5. MessageDispatcher enqueues the event to Message Queue. .
    1. A MessageQueue is one of the core components in forming an Akka Mailbox.
    2. MessageQueue is where the normal messages that are sent to Actors will be enqueued (and subsequently dequeued)
    3. MessageQueue.enqueue() – enqueue the message to this queue, or throw an exception
  6. MessageDispatcher also looks for MailBox (By default every actor has a single mailbox – UnboundedMailbox). Mailbox holds the messages for receiving Actor. Once it finds the MailBox – MessageDispatcher binds a set of Actors to a thread pool (backed by BlockingQueue) and invokes MailBox.run() method
  7. MessageQueue.dequeue() – dequeue the next message from this queue, return null failing that.
  8. Eventually MailBox schedules the task on Actor which invokes receive() method on the Actor.

Example

Assuming you are working on Linux and have Scala + SBT configured and ready to use.

build.sbt 

name := "ScalaWorld"

version := "1.0"

scalaVersion := "2.11.8"

libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.3.4"
libraryDependencies += "org.scala-lang.modules" % "scala-xml_2.11" % "1.0.5"

RunActors.scala

import akka.actor.{Actor, ActorSystem, Props}
import scala.io.Source
import scala.xml._

class WeatherActor extends Actor {
  override def receive: Receive = {
    case msg => println(msg);
  }
}

object RunActors{
  def main(args: Array[String]) {
    val system = ActorSystem("WeatherSystem")
    val weatherActor = system.actorOf(Props[WeatherActor], name = "weatheractor")
    val start = System.nanoTime
    for (id <- 4118 to  4128) {
      weatherActor !  getWeatherInfo(id.toString())
    }
    val end = System.nanoTime
    println("Time : " + (end - start) / 1000000000.0)
    // ActorSystem starts the ThreadPool, so we want to make sure we terminated the ActorSystem when we are done.
    system.shutdown()
  }

def getWeatherInfo(id: String) = {
    val url = "http://weather.yahooapis.com/forecastrss?w=" + id + "&u=c"
    val response = Source.fromURL(url).mkString
    val xmlResponse = XML.loadString(response)
    //Return tuple of 2 values (Tuple2).
    val returnVal = (xmlResponse \\ "location" \\ "@city",
      xmlResponse \\ "condition" \\ "@temp")
    returnVal
  }
}

SBT

cd into you project directory and type sbt

/home/hardik/Downloads/ScalaWorld> sbt
[info] Loading project definition from /home/hardik/Downloads/ScalaWorld/project
[info] Set current project to ScalaWorld (in build file:/home/hardik/Downloads/ScalaWorld/)
> run-main RunActors
[info] Updating {file:/home/hardik/Downloads/ScalaWorld}scalaworld…
[info] Resolving jline#jline;2.12.1 …
[info] Done updating.
[info] Compiling 1 Scala source to /home/hardik/Downloads/ScalaWorld/target/scala-2.11/classes…
[info] Running RunActors

Output:  I am querying Yahoo Weather WebService API and passing WOEID (Where on Earth ID) starting from 4118 to 4128 and fetching City and Temperature information. As you can see I have executed getWeatherInfo()  both with  and without Actors and you can see the execution time difference.

I only touched the surface of Akka Actors – there is a lot to cover which I will cover in next article.

Normal Execution (without Actor System invoking getWeaeherInfo(id.toString())
============================ 
(Toronto,8)
(Halton Hills,8)
(,)
(Milton,8)
(Oakville,8)
(,)
(Burlington,8)
(Hamilton,8)
(St. Catharines,8)
(Welland,8)
(Dunnville,8)
Time : 3.712243053
Execution With Actors
=============================
(Toronto,8)
(Halton Hills,8)
(,)
(Milton,8)
(Oakville,8)
(,)
(Burlington,8)
(Hamilton,8)
(St. Catharines,8)
(Welland,8)
(Dunnville,8)
Time : 1.359151664



Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s