This document provides an introduction to concurrent programming with Akka Actors. It discusses concurrency and parallelism, how the end of Moore's Law necessitated a shift to concurrent programming, and introduces key concepts of actors including message passing concurrency, actor systems, actor operations like sending messages, and more advanced topics like routing, supervision, testing, configuration and remote actors.
2. ● Shashank L
● Senior Software engineer at Tellius
● Part time big data consultant and trainer
at datamantra.io
● www.shashankgowda.com
3. Concurrency
● Concurrency is the decomposability property of a
program, algorithm, or problem into order-independent or
partially-ordered components or units
● Structure a program by breaking it into pieces that can be
executed independently
● Co ordinating the execution of independent pieces
4. Concurrency and parallelism
● Concurrency is dealing with more than one thing at once
● Parallelism is doing more than one thing at once
Given tasks T1 and T2
T1 may be executed and finished before T2 or vice versa
(serial and sequential)
T1 and T2 may be executed alternately
(serial and concurrent)
T1 and T2 may be executed simultaneously at the same instant of time
(parallel and concurrent)
5. Concurrency is not parallelism
● Queues can be thought of
processed/threads
● Vending machine is
processor core
6. Moore’s law
The number of transistors on a chip doubles approximately
every 2 years.
~ Gordon Moore, 1965
7. Free performance lunch
● Over 30 years till 2000, performance gains were in 3
areas
○ Clock speed
○ Execution optimization
○ Caching
Old applications have always run significantly faster
even without being recompiled
8. Moore’s law
● Early 2000
○ Chips got big, transistors were added aggressively
○ Clock cycle was almost unchanged
○ Heat dissipation issues
○ Power consumption
○ Current leakage
10. Birth of Multicore processors
● Multi-core processors
● Handle multiple operations in parallel
● CPU speeds are not increasing drastically anytime soon
● No free performance lunch without significant redesign
● Performance gains in new chips will be fueled by three main
approaches
○ Hyperthreading
○ Multicore
○ cache
11. Free performance lunch is over
● Concurrency revolution
● Build multi core aware applications
● Operate in concurrent fashion
● Scale horizontally
12. Types of Concurrency
● Shared state concurrency
● Software transactional concurrency
● Message passing concurrency
13. Shared state concurrency
● Shared mutability
● Memory blocks can be access simultaneously by multiple
programs
● Race condition
● Dead locks
● Blocking calls
com.shashank.akka.basic.ThreadUnsafeBuffer
14. Software transactional memory
● Shared, managed mutability
● Objects can be mutated only within a transaction
● STM keeps track of changes made in a particular
● Once transaction is completed, it validates and commits the
results
● Validation fails when others have committed the result
● Transaction will be repeated with the updated value.
15. Message passing concurrency
● Isolated mutability
● Mutable objects are isolated from the threads
● Threads will not be able to directly access the objects
● Access to the mutable objects is done through messages
● Sending message can be asynchronous and nonblocking
16. Joe Armstrong’s words
The world is concurrent. It is parallel. Pure message-passing
concurrency is what we do all the time.
Imagine a group of people. They have no shared state.
I have my private memory (in my head) and you have yours. It is NOT
shared. We communicate by passing messages (sound and light
waves). We update our private state based on the reception of these
messages.
That’s Concurrency Oriented Programming in a nutshell.
17. Actors
● From a 1973 paper, written by Carl Hewitt
● First major adoption was done by Ericsson in 80s
○ Invented Erlang and open sourced in 90s
○ Built a distributed, concurrent, and fault-tolerant telcom
system which has 99.9999999% uptime
● Implements Message-Passing or Isolated mutability based
concurrency
18. Actor model
● Share Nothing
○ No need to synchronize.
● Isolated. Lightweight event-based Processes
○ ~ 6.5m on 4GB RAM
● Communicate through Messages
○ Asynchronous and Nonblocking
○ Messages are immutable
● Each actor has a mailbox (message queue)
● Scalable and fast
19. When an Actor receives messages
● Creates new actors
● Send message to other actors/self
● Designate how it should handle the next
message
20. Akka
● Founded by Jonas Boner and now part of Typesafe stack
● Actor implementation on JVM - Scala
○ Java API and Scala API
● Provides a framework to create & manage actors
● Backed by JVM Thread model
● Akka provides a mailbox for each actor
○ in-memory queue to stage messages
● Clients can send messages synchronously or
asynchronously
● Actor receives messages and respond to clients
21.
22. Actor System
● Actors are created within this context
● Fundamental unit that embodies:
Processing, storage and communication
● Manage shared facilities:
scheduling, logging, configuration etc
● Can have many per JVM with different configs
● Can contain millions of actors
25. CREATE
val system = ActorSystem("LogSystem")
val loggerActor = system.actorOf(
Props[LoggerActor],
name = "loggeractor")
26. SEND
● Fire and forget
○ Async
○ No expected reply
○ ! or tell()
● Send and Receive
○ Async
○ Expects reply (Future)
○ ? or ask()
27. SEND - Fire and forget
//No need to return anything in the receive method
def receive = {
case x:Int => println(x)
}
//Send the message and don’t wait for the reply
actorRef ! (100)
com.shashank.akka.basic.SimpleActor
28. SEND - Send and receive
//Use the sender method to get the actorRef of the sender
def receive = {
case "hello" =>
sender() ! ("hello how are you?")
}
//Send the message and get a future back, we can wait for that future to be successful to get
the result
val responseFuture = bufferActor ? ("hello")
responseFuture onSuccess{
case response => println(response)
}
com.shashank.akka.basic.ThreadSafeBuffer
32. BECOME
● Dynamically redefines actor behaviour
● Reactively triggered by message
● Like changing an interface or implementation on-the-fly
com.shashank.akka.basic.ThreadSafeBufferWithLimit
33. How error handling is done in Java
● You are given a single thread of control
● If this thread blows up, you are screwed
● So you need to do all explicit error handling within this single
thread
● Errors do not propagate between threads
● This leads to Defensive programming with
○ Error handling tangled with business logic
○ Error handling scattered all over the code
34. SUPERVISE
● Manage another actor’s failure
● Supervisor receives notification
and it can react upon failure
● Every actor has a default
supervisor strategy
○ Can be overridden
35. SUPERVISE
● On Failure, Supervisor decides what happens next
○ Resume child and keep the internal state
○ Restart child and wipe the internal state
○ Stop child permanently
○ Stop itself and escalate the error
● OneForOneStrategy affects only failed child
● AllForOneStrategy affects all the children
com.shashank.akka.supervision.BasicSupervision
41. Stopping Actors
//Shutting down the Actor System
system.shutdown()
//Sending PoisonPill message
actorRef ? (PoisonPill)
//Shutting the actor from inside the actor
context.stop(self)
//Shutting another actor from inside the actor
context.stop(actorRef)
com.shashank.akka.basic.ShuttingDown
42. Message delivery
● At most once - No guaranteed delivery
● Cheapest
● Highest performance
● Least implementation overhead
● It can be done in a fire-and-forget fashion without keeping
state at the sending end or in the transport mechanism
● At least once - Akka persistence
44. Dispatcher
● Controls and coordinates the message dispatching to the
actors
● Make sure that the resources are optimized and messages
are processed as fast as possible
● Dispatch policies that can be customized(number of cores or
memory available)
48. ● Entity that directs the message from source to the destination actor
● Router is also a type of actor
● Does not make use of the store-and-forward mechanism
● Routers dispatch the incoming messages directly to the destination
actor’s mailboxes
system.actorOf(Props[MyActor].withRouter(RoundRobinRouter(nrOfInstances = 5)))
Routers
49. ● Round robin router
It routes the incoming messages in a circular order to all its routees
● Random router
It randomly selects a routee and routes the message to the same
● Smallest mailbox router
It identifies the actor with the least number of messages in its mailbox and routes the
message to the same
● Broadcast router
It forwards the same message to all the routees
● Scatter gather first completed router
It forwards the message to all its routees as a future, then whichever routee actor responds
back, it takes the results and sends them back to the caller
com.shashank.akka.basic.Router
Types of Routers
50. def preStart(): Unit = ()
def postStop(): Unit = ()
def preRestart(reason: Throwable, message: Option[Any]): Unit = {
context.children foreach { child ⇒
context.stop(child)
}
postStop()
}
def postRestart(reason: Throwable): Unit = {
preStart()
}
Actor API
51. ● A path is a place that can be occupied by a living actor
● When actorOf() is called it assigns an incarnation of the
actor described by the passed Props to the given path
● An ActorRef always represents an incarnation (path and
UID) not just a given path. Another actor created later with
the same name will have a different ActorRef
// will look up this absolute path
context.actorSelection("/user/serviceA/aggregator")
// will look up sibling beneath same supervisor
context.actorSelection("../joe")
Actor Path
53. ● Consists of 2 parts
○ A public interface
○ An implementation
● Similar to Interface and implements in Java, Traits in
Scala
● TypedActors have a static contract
● Some features like become is not available
● Bridging between actor systems (the “inside”) and
non-actor code (the “outside”)
Typed actors
54. def squareDontCare(i: Int): Unit //fire-forget
def square(i: Int): Future[Int] //non-blocking send-request-reply
def squareNowPlease(i: Int): Option[Int] //blocking send-request-reply
def squareNow(i: Int): Int //blocking send-request-reply
@throws(classOf[Exception]) //declare it or you will get an UndeclaredThrowableException
def squareTry(i: Int): Int //blocking send-request-reply with possible exception
//Creating an actorRef of a TypedActor
val mySquarer: Squarer = TypedActor(system).typedActorOf(TypedProps[SquarerImpl]())
com.shashank.akka.basic.TypedActorExample
Typed actors
55. ● Dedicated module akka-testkit for supporting tests
● Testing isolated pieces of code without involving the actor
model, meaning without multiple threads
● Testing (multiple) encapsulated actors including
multi-threaded scheduling
● Integration with ScalaTest to write more readable
assertions
com.shashank.akka.supervision.SupervisorTestSpec
Actor TestKit
56. ● All configuration for Akka is held within instances of ActorSystem
● ActorSystem is the only consumer of configuration information
● Parse the configuration file
val config =
ConfigFactory.parseFile(new File("src/main/resources/router/application.conf"))
val system = ActorSystem("NameOfActorSystem", config)
● Read the configuration files automatically from ClassLoader
val config = ConfigFactory.defaultReference()
val system = ActorSystem("NameOfActorSystem", config)
● Parse all application.conf, application.json and application.properties
● akka.log-config-on-start
Configuration - TypeSafe config
57. ● Distributed by default
● Messages should be and are serializable
● ActorRefs are serializable
● Probability of the message reaching is higher than local
JVM
● No separate remoting layer in Akka. Purely driven by
config
● Communication between involved system is symmetric
● Not possible to create pure client-server setups
Remote Actors
59. In different scenarios Actors can be alternatives for:
● A thread
● An object instance or component
● A callback or listener
● A singleton or service
● A router, load-balancer or pool
● An out-of-service process
● A Finite State machine (FSM)
What can I use Actors for?