SlideShare a Scribd company logo
1 of 59
Download to read offline
The dark side of Akka

and the remedy

V2
My experiences with Akka



Ákos Kriváchy
Introduction - Ákos Kriváchy
• Scala fanatic since 2013 February
• First FP language
• Akka since 2014 February
• Things I love about Scala:
• Static type system
• Type classes
• Partial Functions
• foldLeft, tail recursion, functional features
2
Today’s topic
1. Overview of Akka
2. When to use Akka
3. Some caveats
4. Possible solutions
5. Conclusions
Akka?
Simple and high-level abstractions for
concurrency and parallelism
Actors
• Actor Model
• Lightweight event-driven processes
• 2.7 million actors per GB RAM
• Communication only via messages
• Message processing guaranteed to be on a single thread
6
Source: http://doc.akka.io/docs/akka/snapshot/intro/what-is-akka.html
Image Source: http://www.scottlogic.com/blog/2014/08/15/using-akka-and-scala-to-render-a-mandelbrot-
set.html
Actor implementation
class MyActor extends Actor {
def receive: Receive = {
case Message(data) =>
// ...
case OtherMessage(_) =>
// ...
context.become(otherBehavior)
}
def otherBehavior: Receive = …
}
Behavior:
PartialFunction[Any, Unit]



Approximately in Java:

PartialFunction[Object,
Able to change behavior
Fault Tolerance
• Supervisor hierarchies
• “Let-it-crash" semantics.
• Location transparency
• Different JVMs on different servers on different continents
• Highly fault-tolerant systems
• self-heal and never stop
• Persistence and recovery
• Journaling of all messages
Source: http://doc.akka.io/docs/akka/snapshot/intro/what-is-akka.html
Image Source: http://doc.akka.io/docs/akka/snapshot/general/supervision.html
When to Akka?
•Akka solves for us:
• Parallelism
• Scalability and distributability
• Resilience
•Perfect for:
• Transaction/(semi-)real-time processing
• Backend with high parallelism
• Calculations
• High availability backends
To Akka or not to Akka?
Thinking in Actors
Number of Actors
Only few stateful
components are Actors
Everything is an Actor
Thinking in Actors
Number of Actors
Only few stateful
components are Actors
Everything is an Actor
Super-complicated
logic inside Actors
Complexity in
communication

(“infrastructure”)
Thinking in Actors
Number of Actors
Only few stateful
components are Actors
Everything is an Actor
Monoliths Micro-services
Caveats/Issues
Problem #1: Any and Actor Ref
• All messages are Any-s
• Anything that’s not
handled ends up as a
“dead letter”
• Requires extensive
testing to “feel safe”
class MyActor(databasePersistence: ActorRef,
emailSender : ActorRef,
MQSender : ActorRef,
widgetDao : ActorRef,
twitterService : ActorRef)
extends Actor {
def receive: Receive = {
case Message(data) =>
twitterService ! Tweet(data)
// ...
case OtherMessage(_) =>
// ...
}
}
}
17
def receive: Receive = {


case Message(data) =>


emailSender ! Tweet(data)
// ... 

case OtherMessage(_) =>
// ...
}
def receive: Receive = {


case Message(data) =>


emailSender ! Tweet(data)
// ... 

case OtherMessage(_) =>
// ...
}
BUG
*
* Except Akka
Joking aside:
Theory around static type-checking

state machines is hard
Differing opinions on how severe the issue is (cost vs. benefit):
http://stew.vireo.org/posts/I-hate-akka/
https://www.reddit.com/r/scala/comments/2ruskl/i_hate_akka/
Solution coming: Akka Typed
• Unreleased and experimental
• Defined protocols with types for:
• ActorSystem!
• No user guardian, define your own!
• Actor
• ActorRef
• .tell (!)
• .ask (?)
• More information:
• http://doc.akka.io/docs/akka/snapshot/scala/typed.html
• http://blog.scalac.io/2015/04/30/leszek-akka-typed.html
In the meantime: Don’t use Actors for everything
• IMHO: Benefits outweigh the cost of the loss of type safety in
certain applications
• What do we use instead?
• Scala Futures are extremely powerful
• Futures compose nicer than Actors
• What about supervision and „let it crash”?
• Future’s handle failure also
24
Problem #2: Hellish code complexity
25
var hell
• Actors have too much mutable state
• Our worst scenario: Actor with 300 lines and 20 vars
• Hard to reason about state when everything is “global” inside
the Actor
• How do you initialize state that is only used in some
behaviours?
• var something: SomeType = _
• NPE
• var something: Option[SomeType] = None
• Always need to “getOrElse”
26
become/unbecome hell
• Pushing and popping state on a stack
• context.become(behavior: Receive, discardOld: Boolean = true)
• context.unbecome()
• “context.become” isn’t enforced to be called last
• You use methods to keep things short, but there will be multiple
methods trying to modify the behaviour
• i.e. you could end up inadvertently overwriting behavior
• One place: context.become(handleCoolMessages orElse waitForNewRequests)
• Somewhere else: context.become(waitForNewRequests, discardOld = true)
• When things blow up you have no idea how you got there
27
class Receptionist extends Actor {
def receive = waiting
def waiting: Receive = {
case Api.Scrape(url, depth) =>
context.become(next(Vector(Job(sender, url, depth))))
}
def running(queue: Vector[Job]): Receive = LoggingReceive {
case Result(links) =>
// …
context.become(next(queue.tail))
case Api.Scrape(url, depth) =>
context.become(enqueue(queue, Job(sender, url, depth)))
case Terminated(_) =>
// …
context.become(next(queue.tail))
}
def enqueue(queue: Vector[Job], job: Job): Receive = LoggingReceive {
// …
running(queue)
}
def next(queue: Vector[Job]): Receive = LoggingReceive {
// …
running(queue)
}
}
28
class Receptionist extends Actor {
def receive = waiting
def waiting: Receive = {
case Api.Scrape(url, depth) =>
context.become(next(Vector(Job(sender, url, depth))))
}
def running(queue: Vector[Job]): Receive = LoggingReceive {
case Result(links) =>
// …
context.become(next(queue.tail))
case Api.Scrape(url, depth) =>
context.become(enqueue(queue, Job(sender, url, depth)))
case Terminated(_) =>
// …
context.become(next(queue.tail))
}
def enqueue(queue: Vector[Job], job: Job): Receive = LoggingReceive {
// …
running(queue)
}
def next(queue: Vector[Job]): Receive = LoggingReceive {
// …
running(queue)
}
}
29
Behavior changes
all over the place
Problem #3: Debugging
Debug hell
• Debugging Actors is hard
• Stacktraces lack meaning
• Need to have a lot of boilerplate utility code:
• What was the message?
• Who sent the message?
• What’s my internal state?
31
[ERROR] [akka://simple-actor/user/receptionist/controller-1/$a] Exception happened
java.lang.Exception: exception happened here
at meetup.akka.simple.Getter$$anonfun$receive$1$$anonfun$1.apply(Getter.scala:37)
at meetup.akka.simple.Getter$$anonfun$receive$1$$anonfun$1.apply(Getter.scala:37)
at scala.util.Try$.apply(Try.scala:191)
at meetup.akka.simple.Getter$$anonfun$receive$1.applyOrElse(Getter.scala:37)
at akka.actor.Actor$class.aroundReceive(Actor.scala:465)
at meetup.akka.simple.Getter.aroundReceive(Getter.scala:16)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
at akka.actor.ActorCell.invoke(ActorCell.scala:487)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238)
at akka.dispatch.Mailbox.run(Mailbox.scala:220)
at akka.dispatch.ForkJoinExecutorConfigurator
$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:
107) 32
We need Logging for Debugging
• Akka provides:
• with ActorLogging
• log.info(…)
• LoggingRecieve: def receive = LoggingReceive { … }
• Lifecycle logging: akka.actor.debug.lifecycle=true
• Autorecieve logging: akka.actor.debug.autoreceive=true
• Issue:
• Akka only provides logging of actual messages per Receive block (has
pros and cons)
• If you missed one => good luck debugging issues around it in
production
33
[DEBUG] [akka://simple-actor/user/receptionist] started(meetup.akka.simple.Receptionist@14ba772)
[DEBUG] [akka://simple-actor/user/receptionist/controller-1] started
(meetup.akka.simple.Controller@38a5d7)
[DEBUG] [akka://simple-actor/user/receptionist] now supervising Actor[akka://simple-
actor/user/receptionist/controller-1#4232237]
[DEBUG] [akka://simple-actor/user/receptionist/controller-1] now watched by
Actor[akka://simple-actor/user/receptionist#1565954732]
[DEBUG] [akka://simple-actor/user/receptionist/controller-1] received handled
message Check(http://doc.akka.io/docs/akka/2.3.5/intro/what-is-akka.html,1)
Logging example
34
FSM
37
“Everything* is a Finite State Machine.”**
-me after 7 beers
* not everything

** please do not quote me
38
Code: https://github.com/krivachy/AkkaWithFsm
39
FSM concepts
object Receptionist {
object Internal {
 
sealed trait State
case object Sleeping extends State
case object Processing extends State
 
sealed trait Data
case class NoQueue(requestId: Int = 0) extends Data
case class Queue(currentRequestId: Int, items: Vector[Job]) extends Data
 
}
}
40
States explicitly
defined – just typed
singletons
Data used in states
explicitly defined
class Receptionist

extends FSM[Internal.State, Internal.Data] {…}
Define handlers for all states
// Initialize with data
startWith(Sleeping, NoQueue())

// Handlers for states
when(Sleeping)(enqueueNewRequest)
when(Processing) (

processResult

orElse enqueueNewRequest
orElse reportError
)
42
Isn’t this
nice?
Behaviors
43
• Behavior
• StateFunction: PartialFunction[Event, State]
• Event
• Event(incomingMessage, stateData) => …
• State transitions:
• goto/stay (nextState) using (data) forMax(timeout) replying
(message)
def enqueueNewRequest: StateFunction = {
case Event(Api.Scrape(url, depth), NoQueue(requestId)) =>
// …
case Event(Api.Scrape(url, depth), queue: Queue) =>
if (queue.items.size > 3) {
stay replying Api.Failed(url)
} else {
goto(Processing) using
Queue(queue.currentRequestId, queue.items :+ Job(sender(), url,
depth))
}
}
Message Data in state
State changes
Data changes
Monitoring state transitions
onTransition {
case Idle -> Active => setTimer("timeout", Tick, 1 second, true)
case Active -> _ => cancelTimer("timeout")
case x -> Idle => log.info("entering Idle from " + x)
}
monitoredActor ! SubscribeTransitionCallBack(self)
def recieve = {
case Transition(monitoredActor, oldState, newState) =>
if (newState == Errored) alert.raiseAlert(...)
}
override def postStop() = {
monitoredActor ! UnsubscribeTransitionCallBack(self)
}
Internal:
External:
45
Handling failure
whenUnhandled {
case Event(any, data) =>
val logUpToHere = prettyPrint(getLog)
log.error(s"Unhandled event: ${any}n${logUpToHere}")
stay()
}
46
Handling failure
def handleFailureMessage: StateFunction = {
case Event(Status.Failure(cause), _) =>
log.error(s"Failed to GET $url", cause)
stop(FSM.Failure(cause))
}
onTermination {
case StopEvent(FSM.Normal, state, data) => ???
case StopEvent(FSM.Shutdown, state, data) => ???
case StopEvent(FSM.Failure(cause), state, data) => ???
}
Result is simplicity
class Receptionist extends FSM[Internal.State, Internal.Data] {
startWith(Sleeping, NoQueue())
when(Sleeping)(enqueueNewRequest)
when(Processing) (processResult orElse enqueueNewRequest orElse reportError)
def enqueueNewRequest: StateFunction = ???
def processResult: StateFunction = ???
def reportError: StateFunction = ???
whenUnhandled { ??? }
initialize()
}
48
Possible states
of Actor explicit
Behavior self-
contained
Error handling
common
Hell status
var ✔
No more mutable global state
inside Actors. Everything is
typed to the specific State.
become/unbecome ✔
All methods have to end in a
state transition. States are
clearly defined what they do.
debug/logging ?
49
50
LoggingFSM
• Remembers state transitions:
• Can override size of history (logDepth defaults to 8)
• Works super well with: onTermination
• Debug logging: akka.actor.debug.fsm=true
• Automatically logs important Events: message + internal
data
• Logs state transitions
• Use with: akka.actor.debug.lifecycle=true
51
Debug log example
[DEBUG] [akka://fsm/user/receptionist] processing
Event(Result(Set([…])),Queue(1,Vector(Job(Actor[akka://fsm/
system/testActor1#758674372],http://doc.akka.io/docs/akka/
2.3.5/intro/what-is-akka.html,1)))) from Actor[akka://fsm/
user/receptionist/controller-1#4232237]
[DEBUG] [akka://fsm/user/receptionist/controller-1] transition
CollectingResults -> Completed
[DEBUG] [akka://fsm/user/receptionist] transition Processing -
> Sleeping
[DEBUG] [akka://fsm/user/receptionist/controller-1] stopped
52
Internal state
logged
Incoming
message logged
[ERROR] [akka://fsm/user/receptionist] Unhandled event: some string
Last 8 entries leading up to this point:
in state: Sleeping
with data: NoQueue(2)
received: Scrape(http://non-existent.link,5)
in state: Processing
with data: Queue(3,Vector(Job(Actor[akka://fsm/system/testActor1#758674372],http://
non-existent.link,5)))
received: Result(Set(http://non-existent.link))
[…]
in state: Processing
with data: Queue(4,Vector(Job(Actor[akka://fsm/system/testActor1#758674372],http://
non.existent1,0), Job(Actor[akka://fsm/system/testActor1#758674372],http://
non.existent2,0), Job(Actor[akka://fsm/system/testActor1#758674372],http://
non.existent3,0), Job(Actor[akka://fsm/system/testActor1#758674372],http://
non.existent4,0)))
received: some string
53
Awesome
history of what
happened
Hell status
var ✔
No more mutable global state
inside Actors. Everything is
typed to the specific State.
become/unbecome ✔
All methods have to end in a
state transition. States are
clearly defined what they do.
debug/logging ✔
FSM does all the debug
logging we would ever need.
54
Conclusions
Akka is awesome…
…but you replace one set of
problems for another!
Akka Typed

will help solve some issues
My experiences
•Needs a new mindset
•Unexperienced developers + learning curve +
easy to make mistakes = headaches
•Use Actors only when really needed
• Too much testing of protocols and communication
•Try to make all Actors FSM Actors
•Helps solve issues around Actor complexity
@akoskrivachy https://github.com/krivachy/AkkaWithFsm

More Related Content

What's hot

Command Design Pattern
Command Design PatternCommand Design Pattern
Command Design PatternShahriar Hyder
 
Scripting Your Qt Application
Scripting Your Qt ApplicationScripting Your Qt Application
Scripting Your Qt Applicationaccount inactive
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and EffectsMartin Odersky
 
Java application monitoring with Dropwizard Metrics and graphite
Java application monitoring with Dropwizard Metrics and graphite Java application monitoring with Dropwizard Metrics and graphite
Java application monitoring with Dropwizard Metrics and graphite Roberto Franchini
 
Rate Limiting with NGINX and NGINX Plus
Rate Limiting with NGINX and NGINX PlusRate Limiting with NGINX and NGINX Plus
Rate Limiting with NGINX and NGINX PlusNGINX, Inc.
 
Handling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVMHandling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVMMin-Yih Hsu
 
Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Scott Wlaschin
 
The tests are trying to tell you something@VoxxedBucharest.pptx
The tests are trying to tell you something@VoxxedBucharest.pptxThe tests are trying to tell you something@VoxxedBucharest.pptx
The tests are trying to tell you something@VoxxedBucharest.pptxVictor Rentea
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumlercorehard_by
 
Pharo foreign function interface (FFI) by example by Esteban Lorenzano
Pharo foreign function interface (FFI) by example by Esteban LorenzanoPharo foreign function interface (FFI) by example by Esteban Lorenzano
Pharo foreign function interface (FFI) by example by Esteban LorenzanoFAST
 
Design Principles for a High-Performance Smalltalk
Design Principles for a High-Performance SmalltalkDesign Principles for a High-Performance Smalltalk
Design Principles for a High-Performance SmalltalkESUG
 
Design and Implementation of GCC Register Allocation
Design and Implementation of GCC Register AllocationDesign and Implementation of GCC Register Allocation
Design and Implementation of GCC Register AllocationKito Cheng
 
Software Development Best Practices: Separating UI from Business Logic
Software Development Best Practices: Separating UI from Business LogicSoftware Development Best Practices: Separating UI from Business Logic
Software Development Best Practices: Separating UI from Business LogicICS
 
Scylla core dump debugging tools
Scylla core dump debugging toolsScylla core dump debugging tools
Scylla core dump debugging toolsTomasz Grabiec
 
Git, CMake, Conan - How to ship and reuse our C++ projects?
Git, CMake, Conan - How to ship and reuse our C++ projects?Git, CMake, Conan - How to ship and reuse our C++ projects?
Git, CMake, Conan - How to ship and reuse our C++ projects?Mateusz Pusz
 
RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)Tracy Lee
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeScott Wlaschin
 
Lesson 17: Inverse Trigonometric Functions
Lesson 17: Inverse Trigonometric FunctionsLesson 17: Inverse Trigonometric Functions
Lesson 17: Inverse Trigonometric FunctionsMatthew Leingang
 
Introduction to the Qt Quick Scene Graph
Introduction to the Qt Quick Scene GraphIntroduction to the Qt Quick Scene Graph
Introduction to the Qt Quick Scene GraphICS
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummiesLuis Goldster
 

What's hot (20)

Command Design Pattern
Command Design PatternCommand Design Pattern
Command Design Pattern
 
Scripting Your Qt Application
Scripting Your Qt ApplicationScripting Your Qt Application
Scripting Your Qt Application
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
Java application monitoring with Dropwizard Metrics and graphite
Java application monitoring with Dropwizard Metrics and graphite Java application monitoring with Dropwizard Metrics and graphite
Java application monitoring with Dropwizard Metrics and graphite
 
Rate Limiting with NGINX and NGINX Plus
Rate Limiting with NGINX and NGINX PlusRate Limiting with NGINX and NGINX Plus
Rate Limiting with NGINX and NGINX Plus
 
Handling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVMHandling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVM
 
Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...
 
The tests are trying to tell you something@VoxxedBucharest.pptx
The tests are trying to tell you something@VoxxedBucharest.pptxThe tests are trying to tell you something@VoxxedBucharest.pptx
The tests are trying to tell you something@VoxxedBucharest.pptx
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
 
Pharo foreign function interface (FFI) by example by Esteban Lorenzano
Pharo foreign function interface (FFI) by example by Esteban LorenzanoPharo foreign function interface (FFI) by example by Esteban Lorenzano
Pharo foreign function interface (FFI) by example by Esteban Lorenzano
 
Design Principles for a High-Performance Smalltalk
Design Principles for a High-Performance SmalltalkDesign Principles for a High-Performance Smalltalk
Design Principles for a High-Performance Smalltalk
 
Design and Implementation of GCC Register Allocation
Design and Implementation of GCC Register AllocationDesign and Implementation of GCC Register Allocation
Design and Implementation of GCC Register Allocation
 
Software Development Best Practices: Separating UI from Business Logic
Software Development Best Practices: Separating UI from Business LogicSoftware Development Best Practices: Separating UI from Business Logic
Software Development Best Practices: Separating UI from Business Logic
 
Scylla core dump debugging tools
Scylla core dump debugging toolsScylla core dump debugging tools
Scylla core dump debugging tools
 
Git, CMake, Conan - How to ship and reuse our C++ projects?
Git, CMake, Conan - How to ship and reuse our C++ projects?Git, CMake, Conan - How to ship and reuse our C++ projects?
Git, CMake, Conan - How to ship and reuse our C++ projects?
 
RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-Toe
 
Lesson 17: Inverse Trigonometric Functions
Lesson 17: Inverse Trigonometric FunctionsLesson 17: Inverse Trigonometric Functions
Lesson 17: Inverse Trigonometric Functions
 
Introduction to the Qt Quick Scene Graph
Introduction to the Qt Quick Scene GraphIntroduction to the Qt Quick Scene Graph
Introduction to the Qt Quick Scene Graph
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummies
 

Similar to The dark side of Akka and the remedy

The dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetupThe dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetupkrivachy
 
Reactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysReactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysManuel Bernhardt
 
Akka london scala_user_group
Akka london scala_user_groupAkka london scala_user_group
Akka london scala_user_groupSkills Matter
 
Developing a Real-time Engine with Akka, Cassandra, and Spray
Developing a Real-time Engine with Akka, Cassandra, and SprayDeveloping a Real-time Engine with Akka, Cassandra, and Spray
Developing a Real-time Engine with Akka, Cassandra, and SprayJacob Park
 
Advanced akka features
Advanced akka featuresAdvanced akka features
Advanced akka featuresGrzegorz Duda
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkBen Scofield
 
From polling to real time: Scala, Akka, and Websockets from scratch
From polling to real time: Scala, Akka, and Websockets from scratchFrom polling to real time: Scala, Akka, and Websockets from scratch
From polling to real time: Scala, Akka, and Websockets from scratchSergi González Pérez
 
Asynchronous Orchestration DSL on squbs
Asynchronous Orchestration DSL on squbsAsynchronous Orchestration DSL on squbs
Asynchronous Orchestration DSL on squbsAnil Gursel
 
The things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and AkkaThe things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and AkkaKonrad Malawski
 
Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)mircodotta
 
Akka lsug skills matter
Akka lsug skills matterAkka lsug skills matter
Akka lsug skills matterSkills Matter
 
Scaling Web Apps with Akka
Scaling Web Apps with AkkaScaling Web Apps with Akka
Scaling Web Apps with AkkaMaciej Matyjas
 
A gentle introduction into AKKA and the actor model
A gentle introduction into AKKA and the actor modelA gentle introduction into AKKA and the actor model
A gentle introduction into AKKA and the actor modelMykhailo Kotsur
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Mario Camou Riveroll
 
Developing distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka ClusterDeveloping distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka ClusterKonstantin Tsykulenko
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)tarcieri
 
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsFresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsKonrad Malawski
 
Concurrency on the JVM
Concurrency on the JVMConcurrency on the JVM
Concurrency on the JVMVaclav Pech
 

Similar to The dark side of Akka and the remedy (20)

The dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetupThe dark side of Akka and the remedy - bp.scala meetup
The dark side of Akka and the remedy - bp.scala meetup
 
Reactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysReactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDays
 
Scale up your thinking
Scale up your thinkingScale up your thinking
Scale up your thinking
 
Akka london scala_user_group
Akka london scala_user_groupAkka london scala_user_group
Akka london scala_user_group
 
Developing a Real-time Engine with Akka, Cassandra, and Spray
Developing a Real-time Engine with Akka, Cassandra, and SprayDeveloping a Real-time Engine with Akka, Cassandra, and Spray
Developing a Real-time Engine with Akka, Cassandra, and Spray
 
Advanced akka features
Advanced akka featuresAdvanced akka features
Advanced akka features
 
Akka patterns
Akka patternsAkka patterns
Akka patterns
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
 
From polling to real time: Scala, Akka, and Websockets from scratch
From polling to real time: Scala, Akka, and Websockets from scratchFrom polling to real time: Scala, Akka, and Websockets from scratch
From polling to real time: Scala, Akka, and Websockets from scratch
 
Asynchronous Orchestration DSL on squbs
Asynchronous Orchestration DSL on squbsAsynchronous Orchestration DSL on squbs
Asynchronous Orchestration DSL on squbs
 
The things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and AkkaThe things we don't see – stories of Software, Scala and Akka
The things we don't see – stories of Software, Scala and Akka
 
Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)
 
Akka lsug skills matter
Akka lsug skills matterAkka lsug skills matter
Akka lsug skills matter
 
Scaling Web Apps with Akka
Scaling Web Apps with AkkaScaling Web Apps with Akka
Scaling Web Apps with Akka
 
A gentle introduction into AKKA and the actor model
A gentle introduction into AKKA and the actor modelA gentle introduction into AKKA and the actor model
A gentle introduction into AKKA and the actor model
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?
 
Developing distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka ClusterDeveloping distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka Cluster
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)
 
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsFresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
 
Concurrency on the JVM
Concurrency on the JVMConcurrency on the JVM
Concurrency on the JVM
 

Recently uploaded

Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 

Recently uploaded (20)

Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 

The dark side of Akka and the remedy

  • 1. The dark side of Akka
 and the remedy
 V2 My experiences with Akka
 
 Ákos Kriváchy
  • 2. Introduction - Ákos Kriváchy • Scala fanatic since 2013 February • First FP language • Akka since 2014 February • Things I love about Scala: • Static type system • Type classes • Partial Functions • foldLeft, tail recursion, functional features 2
  • 3. Today’s topic 1. Overview of Akka 2. When to use Akka 3. Some caveats 4. Possible solutions 5. Conclusions
  • 5. Simple and high-level abstractions for concurrency and parallelism
  • 6. Actors • Actor Model • Lightweight event-driven processes • 2.7 million actors per GB RAM • Communication only via messages • Message processing guaranteed to be on a single thread 6 Source: http://doc.akka.io/docs/akka/snapshot/intro/what-is-akka.html
  • 8. Actor implementation class MyActor extends Actor { def receive: Receive = { case Message(data) => // ... case OtherMessage(_) => // ... context.become(otherBehavior) } def otherBehavior: Receive = … } Behavior: PartialFunction[Any, Unit]
 
 Approximately in Java:
 PartialFunction[Object, Able to change behavior
  • 9. Fault Tolerance • Supervisor hierarchies • “Let-it-crash" semantics. • Location transparency • Different JVMs on different servers on different continents • Highly fault-tolerant systems • self-heal and never stop • Persistence and recovery • Journaling of all messages Source: http://doc.akka.io/docs/akka/snapshot/intro/what-is-akka.html
  • 12. •Akka solves for us: • Parallelism • Scalability and distributability • Resilience •Perfect for: • Transaction/(semi-)real-time processing • Backend with high parallelism • Calculations • High availability backends To Akka or not to Akka?
  • 13. Thinking in Actors Number of Actors Only few stateful components are Actors Everything is an Actor
  • 14. Thinking in Actors Number of Actors Only few stateful components are Actors Everything is an Actor Super-complicated logic inside Actors Complexity in communication
 (“infrastructure”)
  • 15. Thinking in Actors Number of Actors Only few stateful components are Actors Everything is an Actor Monoliths Micro-services
  • 17. Problem #1: Any and Actor Ref • All messages are Any-s • Anything that’s not handled ends up as a “dead letter” • Requires extensive testing to “feel safe” class MyActor(databasePersistence: ActorRef, emailSender : ActorRef, MQSender : ActorRef, widgetDao : ActorRef, twitterService : ActorRef) extends Actor { def receive: Receive = { case Message(data) => twitterService ! Tweet(data) // ... case OtherMessage(_) => // ... } } } 17
  • 18. def receive: Receive = { 
 case Message(data) => 
 emailSender ! Tweet(data) // ... 
 case OtherMessage(_) => // ... }
  • 19. def receive: Receive = { 
 case Message(data) => 
 emailSender ! Tweet(data) // ... 
 case OtherMessage(_) => // ... } BUG
  • 20.
  • 22. Joking aside: Theory around static type-checking
 state machines is hard Differing opinions on how severe the issue is (cost vs. benefit): http://stew.vireo.org/posts/I-hate-akka/ https://www.reddit.com/r/scala/comments/2ruskl/i_hate_akka/
  • 23. Solution coming: Akka Typed • Unreleased and experimental • Defined protocols with types for: • ActorSystem! • No user guardian, define your own! • Actor • ActorRef • .tell (!) • .ask (?) • More information: • http://doc.akka.io/docs/akka/snapshot/scala/typed.html • http://blog.scalac.io/2015/04/30/leszek-akka-typed.html
  • 24. In the meantime: Don’t use Actors for everything • IMHO: Benefits outweigh the cost of the loss of type safety in certain applications • What do we use instead? • Scala Futures are extremely powerful • Futures compose nicer than Actors • What about supervision and „let it crash”? • Future’s handle failure also 24
  • 25. Problem #2: Hellish code complexity 25
  • 26. var hell • Actors have too much mutable state • Our worst scenario: Actor with 300 lines and 20 vars • Hard to reason about state when everything is “global” inside the Actor • How do you initialize state that is only used in some behaviours? • var something: SomeType = _ • NPE • var something: Option[SomeType] = None • Always need to “getOrElse” 26
  • 27. become/unbecome hell • Pushing and popping state on a stack • context.become(behavior: Receive, discardOld: Boolean = true) • context.unbecome() • “context.become” isn’t enforced to be called last • You use methods to keep things short, but there will be multiple methods trying to modify the behaviour • i.e. you could end up inadvertently overwriting behavior • One place: context.become(handleCoolMessages orElse waitForNewRequests) • Somewhere else: context.become(waitForNewRequests, discardOld = true) • When things blow up you have no idea how you got there 27
  • 28. class Receptionist extends Actor { def receive = waiting def waiting: Receive = { case Api.Scrape(url, depth) => context.become(next(Vector(Job(sender, url, depth)))) } def running(queue: Vector[Job]): Receive = LoggingReceive { case Result(links) => // … context.become(next(queue.tail)) case Api.Scrape(url, depth) => context.become(enqueue(queue, Job(sender, url, depth))) case Terminated(_) => // … context.become(next(queue.tail)) } def enqueue(queue: Vector[Job], job: Job): Receive = LoggingReceive { // … running(queue) } def next(queue: Vector[Job]): Receive = LoggingReceive { // … running(queue) } } 28
  • 29. class Receptionist extends Actor { def receive = waiting def waiting: Receive = { case Api.Scrape(url, depth) => context.become(next(Vector(Job(sender, url, depth)))) } def running(queue: Vector[Job]): Receive = LoggingReceive { case Result(links) => // … context.become(next(queue.tail)) case Api.Scrape(url, depth) => context.become(enqueue(queue, Job(sender, url, depth))) case Terminated(_) => // … context.become(next(queue.tail)) } def enqueue(queue: Vector[Job], job: Job): Receive = LoggingReceive { // … running(queue) } def next(queue: Vector[Job]): Receive = LoggingReceive { // … running(queue) } } 29 Behavior changes all over the place
  • 31. Debug hell • Debugging Actors is hard • Stacktraces lack meaning • Need to have a lot of boilerplate utility code: • What was the message? • Who sent the message? • What’s my internal state? 31
  • 32. [ERROR] [akka://simple-actor/user/receptionist/controller-1/$a] Exception happened java.lang.Exception: exception happened here at meetup.akka.simple.Getter$$anonfun$receive$1$$anonfun$1.apply(Getter.scala:37) at meetup.akka.simple.Getter$$anonfun$receive$1$$anonfun$1.apply(Getter.scala:37) at scala.util.Try$.apply(Try.scala:191) at meetup.akka.simple.Getter$$anonfun$receive$1.applyOrElse(Getter.scala:37) at akka.actor.Actor$class.aroundReceive(Actor.scala:465) at meetup.akka.simple.Getter.aroundReceive(Getter.scala:16) at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516) at akka.actor.ActorCell.invoke(ActorCell.scala:487) at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238) at akka.dispatch.Mailbox.run(Mailbox.scala:220) at akka.dispatch.ForkJoinExecutorConfigurator $AkkaForkJoinTask.exec(AbstractDispatcher.scala:393) at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java: 107) 32
  • 33. We need Logging for Debugging • Akka provides: • with ActorLogging • log.info(…) • LoggingRecieve: def receive = LoggingReceive { … } • Lifecycle logging: akka.actor.debug.lifecycle=true • Autorecieve logging: akka.actor.debug.autoreceive=true • Issue: • Akka only provides logging of actual messages per Receive block (has pros and cons) • If you missed one => good luck debugging issues around it in production 33
  • 34. [DEBUG] [akka://simple-actor/user/receptionist] started(meetup.akka.simple.Receptionist@14ba772) [DEBUG] [akka://simple-actor/user/receptionist/controller-1] started (meetup.akka.simple.Controller@38a5d7) [DEBUG] [akka://simple-actor/user/receptionist] now supervising Actor[akka://simple- actor/user/receptionist/controller-1#4232237] [DEBUG] [akka://simple-actor/user/receptionist/controller-1] now watched by Actor[akka://simple-actor/user/receptionist#1565954732] [DEBUG] [akka://simple-actor/user/receptionist/controller-1] received handled message Check(http://doc.akka.io/docs/akka/2.3.5/intro/what-is-akka.html,1) Logging example 34
  • 35.
  • 36.
  • 38. “Everything* is a Finite State Machine.”** -me after 7 beers * not everything
 ** please do not quote me 38
  • 40. FSM concepts object Receptionist { object Internal {   sealed trait State case object Sleeping extends State case object Processing extends State   sealed trait Data case class NoQueue(requestId: Int = 0) extends Data case class Queue(currentRequestId: Int, items: Vector[Job]) extends Data   } } 40 States explicitly defined – just typed singletons Data used in states explicitly defined
  • 42. Define handlers for all states // Initialize with data startWith(Sleeping, NoQueue())
 // Handlers for states when(Sleeping)(enqueueNewRequest) when(Processing) (
 processResult
 orElse enqueueNewRequest orElse reportError ) 42 Isn’t this nice?
  • 43. Behaviors 43 • Behavior • StateFunction: PartialFunction[Event, State] • Event • Event(incomingMessage, stateData) => … • State transitions: • goto/stay (nextState) using (data) forMax(timeout) replying (message)
  • 44. def enqueueNewRequest: StateFunction = { case Event(Api.Scrape(url, depth), NoQueue(requestId)) => // … case Event(Api.Scrape(url, depth), queue: Queue) => if (queue.items.size > 3) { stay replying Api.Failed(url) } else { goto(Processing) using Queue(queue.currentRequestId, queue.items :+ Job(sender(), url, depth)) } } Message Data in state State changes Data changes
  • 45. Monitoring state transitions onTransition { case Idle -> Active => setTimer("timeout", Tick, 1 second, true) case Active -> _ => cancelTimer("timeout") case x -> Idle => log.info("entering Idle from " + x) } monitoredActor ! SubscribeTransitionCallBack(self) def recieve = { case Transition(monitoredActor, oldState, newState) => if (newState == Errored) alert.raiseAlert(...) } override def postStop() = { monitoredActor ! UnsubscribeTransitionCallBack(self) } Internal: External: 45
  • 46. Handling failure whenUnhandled { case Event(any, data) => val logUpToHere = prettyPrint(getLog) log.error(s"Unhandled event: ${any}n${logUpToHere}") stay() } 46
  • 47. Handling failure def handleFailureMessage: StateFunction = { case Event(Status.Failure(cause), _) => log.error(s"Failed to GET $url", cause) stop(FSM.Failure(cause)) } onTermination { case StopEvent(FSM.Normal, state, data) => ??? case StopEvent(FSM.Shutdown, state, data) => ??? case StopEvent(FSM.Failure(cause), state, data) => ??? }
  • 48. Result is simplicity class Receptionist extends FSM[Internal.State, Internal.Data] { startWith(Sleeping, NoQueue()) when(Sleeping)(enqueueNewRequest) when(Processing) (processResult orElse enqueueNewRequest orElse reportError) def enqueueNewRequest: StateFunction = ??? def processResult: StateFunction = ??? def reportError: StateFunction = ??? whenUnhandled { ??? } initialize() } 48 Possible states of Actor explicit Behavior self- contained Error handling common
  • 49. Hell status var ✔ No more mutable global state inside Actors. Everything is typed to the specific State. become/unbecome ✔ All methods have to end in a state transition. States are clearly defined what they do. debug/logging ? 49
  • 50. 50
  • 51. LoggingFSM • Remembers state transitions: • Can override size of history (logDepth defaults to 8) • Works super well with: onTermination • Debug logging: akka.actor.debug.fsm=true • Automatically logs important Events: message + internal data • Logs state transitions • Use with: akka.actor.debug.lifecycle=true 51
  • 52. Debug log example [DEBUG] [akka://fsm/user/receptionist] processing Event(Result(Set([…])),Queue(1,Vector(Job(Actor[akka://fsm/ system/testActor1#758674372],http://doc.akka.io/docs/akka/ 2.3.5/intro/what-is-akka.html,1)))) from Actor[akka://fsm/ user/receptionist/controller-1#4232237] [DEBUG] [akka://fsm/user/receptionist/controller-1] transition CollectingResults -> Completed [DEBUG] [akka://fsm/user/receptionist] transition Processing - > Sleeping [DEBUG] [akka://fsm/user/receptionist/controller-1] stopped 52 Internal state logged Incoming message logged
  • 53. [ERROR] [akka://fsm/user/receptionist] Unhandled event: some string Last 8 entries leading up to this point: in state: Sleeping with data: NoQueue(2) received: Scrape(http://non-existent.link,5) in state: Processing with data: Queue(3,Vector(Job(Actor[akka://fsm/system/testActor1#758674372],http:// non-existent.link,5))) received: Result(Set(http://non-existent.link)) […] in state: Processing with data: Queue(4,Vector(Job(Actor[akka://fsm/system/testActor1#758674372],http:// non.existent1,0), Job(Actor[akka://fsm/system/testActor1#758674372],http:// non.existent2,0), Job(Actor[akka://fsm/system/testActor1#758674372],http:// non.existent3,0), Job(Actor[akka://fsm/system/testActor1#758674372],http:// non.existent4,0))) received: some string 53 Awesome history of what happened
  • 54. Hell status var ✔ No more mutable global state inside Actors. Everything is typed to the specific State. become/unbecome ✔ All methods have to end in a state transition. States are clearly defined what they do. debug/logging ✔ FSM does all the debug logging we would ever need. 54
  • 57. …but you replace one set of problems for another!
  • 58. Akka Typed
 will help solve some issues
  • 59. My experiences •Needs a new mindset •Unexperienced developers + learning curve + easy to make mistakes = headaches •Use Actors only when really needed • Too much testing of protocols and communication •Try to make all Actors FSM Actors •Helps solve issues around Actor complexity @akoskrivachy https://github.com/krivachy/AkkaWithFsm