Introduction to concurrent programming with akka actors
-
Upload
datamantra -
Category
Technology
-
view
86 -
download
1
Transcript of Introduction to concurrent programming with akka actors
Introduction to Concurrent programming
withAkka Actors
https://github.com/shashankgowdal/introduction-to-concurrentprogramming-with-akka
● Shashank L
● Senior Software engineer at Tellius
● Part time big data consultant and trainer at datamantra.io
● www.shashankgowda.com
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
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)
Concurrency is not parallelism
● Queues can be thought of processed/threads
● Vending machine is processor core
Moore’s law
The number of transistors on a chip doubles approximately every 2 years.
~ Gordon Moore, 1965
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
Moore’s law● Early 2000
○ Chips got big, transistors were added aggressively○ Clock cycle was almost unchanged○ Heat dissipation issues○ Power consumption○ Current leakage
Moore’s law
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
Free performance lunch is over● Concurrency revolution
● Build multi core aware applications
● Operate in concurrent fashion
● Scale horizontally
Types of Concurrency● Shared state concurrency
● Software transactional concurrency
● Message passing concurrency
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
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.
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
Joe Armstrong’s wordsThe 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.
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
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
When an Actor receives messages● Creates new actors● Send message to other actors/self● Designate how it should handle the next
message
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
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
val system = ActorSystem("NameForActorSystem")
ACTOR OPERATIONS
DEFINE
class LoggerActor extends Actor {
def receive = {
case x:String => println(x)
case _ => println("huh?")
}
}
CREATE
val system = ActorSystem("LogSystem")
val loggerActor = system.actorOf(
Props[LoggerActor],
name = "loggeractor")
SEND● Fire and forget
○ Async○ No expected reply○ ! or tell()
● Send and Receive○ Async○ Expects reply (Future)○ ? or ask()
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
SEND - Send and receive//Use the sender method to get the actorRef of the senderdef 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 resultval responseFuture = bufferActor ? ("hello")
responseFuture onSuccess{
case response => println(response)
} com.shashank.akka.basic.ThreadSafeBuffer
ActorRef
ActorRef Mailbox ActorInstance
Points to ActorDelivers to Mailbox
Mailbox
ActorRef Mailbox ActorInstance
Invokes Actor Instance with MessageRuns on dispatcher - abstracts threading
ActorInstance
ActorRef Mailbox ActorInstance
Your code here
BECOME● Dynamically redefines actor behaviour
● Reactively triggered by message
● Like changing an interface or implementation on-the-fly
com.shashank.akka.basic.ThreadSafeBufferWithLimit
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
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
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 childrencom.shashank.akka.supervision.BasicSupervision
SUPERVISE - OneForOneStrategy
SUPERVISE - AllForOneStrategy
Actor can form a hierarchy
Actor can form a hierarchy
Name resolution - like a file system
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
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
Message ordering● Message ordering per sender-receiver pair
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)
Dispatcher● Runways - Threads● Airlines - Mailboxes● ATC - Dispatcher or
Dispatch policy
Dispatcher
Dispatcher and Mailboxes Types of dispatchers● Dispatcher● Pinned dispatcher● Balancing dispatcher● Calling thread dispatcher
Mailbox implementations● Unbounded mailbox● Bounded mailbox● Unbounded priority mailbox● Bounded priority mailbox
● 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 mailboxessystem.actorOf(Props[MyActor].withRouter(RoundRobinRouter(nrOfInstances = 5)))
Routers
● Round robin routerIt routes the incoming messages in a circular order to all its routees
● Random routerIt randomly selects a routee and routes the message to the same
● Smallest mailbox routerIt identifies the actor with the least number of messages in its mailbox and routes the message to the same
● Broadcast routerIt forwards the same message to all the routees
● Scatter gather first completed routerIt 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
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
● 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
Actor life-cycle
● 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
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
● 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
assertionscom.shashank.akka.supervision.SupervisorTestSpec
Actor TestKit
● All configuration for Akka is held within instances of ActorSystem
● ActorSystem is the only consumer of configuration information
● Parse the configuration fileval config =
ConfigFactory.parseFile(new File("src/main/resources/router/application.conf"))
val system = ActorSystem("NameOfActorSystem", config)
● Read the configuration files automatically from ClassLoaderval 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
● 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
Remote Actors
com.shashank.akka.remote
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?
● http://doc.akka.io/docs/akka/2.4/scala
● http://blog.madhukaraphatak.com/simple-akka-remote-example/
● https://www.youtube.com/watch?v=W_l57iyn4mUProgramming with Actors by Venkat
● https://www.slideshare.net/jboner/introducing-akka
● https://www.slideshare.net/RoyRusso1/introduction-to-akka-atlanta-java-users-group
● https://blog.golang.org/concurrency-is-not-parallelism
References