8 akka anti-patterns you'd better be aware of - Reactive Summit Austin 2017
1. 8 AKKA ANTI-PATTERNS
YOU'D BETTER BE AWARE OF
REACTIVE SUMMIT AUSTIN 2017
MANUEL BERNHARDT
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
2. WHY THIS TALK?
Tools, of course, can be the subtlest of traps
— Neil Gaiman
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
3. MANUEL.BERNHARDT.IO
> Helping companies to get started with
reactive systems...
> ... or to keep going
> Lightbend training partner
(Akka Professional & Expert)
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
4. MANUEL.BERNHARDT.IO
> Helping companies to get started with
reactive systems...
> ... or to keep going
> Lightbend training partner
(Akka Professional & Expert)
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
8. > it's okay for an actor to have mutable state
> as long as it retains total control over it and is the
only one to see it
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
9. HOW CAN IT HAPPEN?
> reference to mutable state in messages
> closing over mutable state in asynchronous calls
> passing shared mutable state to an actor's
constructor
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
10. WHY IS THIS BAD?
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
15. WHAT TO DO INSTEAD
> use immutable messages for state updates (e.g.
broadcasting for configuration changes)
> use queries for state inquiries (e.g. using the ask
pattern)
> for asynchronous calls, always use the pipe pattern
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
16. ASK AND PIPE
def receive = {
case RetrieveDocumentContent(documentId) =>
val url = computeFileURL(documentId)
implicit val timeout = Timeout(5.seconds) // establish a boundary in time
val file: Future[FetchedFile] = fileFetcher ? FileFetcher.Fetch(url, documentId)
val result = file.recover { case t: AskTimeoutException =>
FileFetchFailure(documentId) // capture the context (documentId)
}
result pipeTo self
case FileFetcher.FetchSuccess(data, documentId) =>
// life is good. do something with the data
case FileFetcher.FileFetchFailure(documentId) =>
// despair. winter is here and you are, like, really cold. all you have is a documentId
}
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
21. HOW CAN IT HAPPEN?
"Ceci n'est pas une hierarchie" - Magritte, 1928
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
22. IF YOUR ACTOR SYSTEM HAS NO HIERARCHY
YOU ARE MISSING THE POINT.
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
23. WHY IS THIS BAD?
> actor systems are designed to handle failures through
hierarchy
> ergo: no hierarchy, no failure handling
> why then bother to use actors in the first place?
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
24. How exception catch blocks are used in Java projects 1
1
Analysis of Exception Handling Patterns in Java Projects: An Empirical Study (S. Nakshatri, M. Hegde, S. Thandra)
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
25. WHAT TO DO INSTEAD?
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
26. WHAT TO DO INSTEAD?
Build hierarchies.
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
28. The mother of excess is not joy
but joylessness.
— Friedrich Nietzsche
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
29. ANTI-PATTERN #3
TOO MANY ACTOR SYSTEMS
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
30. HOW CAN IT HAPPEN?
> eagerly wanting to isolate things
> and not understanding how Akka
works
(but the intent is good)
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
31. WHY IS THIS BAD?
> each actor system has at least one dispatcher backed
by a thread pool
> multiple actor systems = multiple thread pools,
contending for the same resources
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
32. WHAT TO DO INTEAD?
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
33. WHAT TO DO INSTEAD?
Bulkheading with custom dispatchers
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
38. HOW CAN THIS HAPPEN?
> string concatentation
log().debug("Received message: " + msg.toString());
> non-asynchronous logging
> not turning debug logging off in
production settings
> let's get real: logging to files (it is
2017)
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
39. WHY IS THIS BAD?
> actor sytems are meant to process millions of
messages per second
> getting logging wrong has a huge performance impact
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
40. WHAT TO DO INSTEAD?
> use Akka's built-in logging facility
> carefully configure the logback appenders, use
asynchronous variants
> log().debug("Received message {}", msg);
> use a logging aggregation mechanism (logstash &
friends)
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
42. All that we see or seem is but a
dream within a dream.
— Edgar Allan Poe
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
43. ANTI-PATTERN #5BEING OUT OF TOUCH WITH THE HARDWARE
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
44. HOW CAN THIS HAPPEN?
XKCDE 2
2
http://xkcd.com/1764/
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
45. WHY IS THIS A BAD THING?
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
46. WHY IS THIS A BAD THING?
fork-join-executor {
# Min number of threads to cap factor-based parallelism number to
parallelism-min = 2
# Parallelism (threads) ... ceil(available processors * factor)
parallelism-factor = 2.0
# Max number of threads to cap factor-based parallelism number to
parallelism-max = 10
}
ceil(available processors * factor)
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
47. WHY IS THIS BAD?
> suboptimal or simply wrong configuration for the
amount of CPU cores
> costs of context switching
> contending for network
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
48. WHAT TO DO INSTEAD?
> know your hardware and configure accordingly
> beware of virtualization (is the hypervisor lying to
you?)
> run load tests on the same hardware as your target
production system
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
50. "...some men aren't looking for
anything logical, like money. They
can't be bought, bullied, reasoned,
or negotiated with. Some men just
want to watch the world burn."
— Alfred Pennyworth, Batman, The Dark Knight
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
52. HOW CAN THIS HAPPEN?
> calling a synchronous API
> or calling an API that calls an API that calls an API...
that calls a synchronous API
> explicitly waiting for the completion of a Future
(Await.result)
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
53.
54. WHAT TO DO INSTEAD?
> if you really must (legacy API), use a dedicated
dispatcher optimized for the blocking case (and limited
in resources)
> use the akka scheduler if you are waiting for something
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
55. The desire of excessive power
caused the angels to fall
— Francis Bacon
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
60. WHY IS IT BAD?
> The third rule of Distributed Systems Club is:
"Don't trust the network"
> you will need to implement a failure detector and take
appropriate actions
> for a multi-node application, you will need to implement
some form of gossiping
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
61. WHAT TO DO INSTEAD?
> use Akka cluster!
> membership service - who is there, who may be not
> Φ accrual failure detector
> gossip based on Amazon Dynamo & Basho's Riak
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
62. BUT REMEMBER: YOU'RE STILL ON THE
NETWORK
> there ain't no such thing as a free lunch
> network partitions can occur, make sure to have a
split brain resolver
> know your failure detector - especially when operating
on cloud platforms 3
3
https://manuel.bernhardt.io/2017/07/26/a-new-adaptive-accrual-failure-detector-for-akka/
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
66. HOW CAN THIS HAPPEN?
> leaving the default on
> Java serialization over the wire
> Java serialization in Akka Persistance
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
67. WHY IS IT BAD?
> performance penalty!
> poor candidate for protocol evolution - message
evolutions result in older components not able to
process them any longer
> persistance - messages and snapshots can't be
processed any longer after changes
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
68. WHAT TO DO INSTEAD?
> use a proper binary format from the start
> once you're in production, it's kind of too late
> protobuf, avro, thrift
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu
69. THANK YOU
> Questions, comments, feedback?
> Contact me at manuel@bernhardt.io / @elmanu
> Check out more anti-patterns at
https://manuel.bernhardt.io
Reactive Summit Austin 2017 - https://manuel.bernhardt.io - @elmanu