I gave this presentation to my coworkers recently. Unfortunately, the animations done translate to PDF so it's a tad sucky, but the main content is there.
4. Akka is Concurrency
Actors: Living objects with concurrent context
Futures: These aren’t Java’s Futures
val
futureData
=
for
{
response
<-‐
httpGet(…)
query
=
response.body.as[Query]
(img,
text)
<-‐
imageQuery(query)
scaledImg
<-‐
scaleImg(img)
}
yield
NewPostData(text,
scaledImg)
“I am for you,
Alrik of Valt.”
5. Akka is Concurrency
Actors: Living objects with concurrent context
Futures: These aren’t Java’s Futures
val
futureData
=
for
{
response
<-‐
httpGet(…)
query
=
response.body.as[Query]
(img,
text)
<-‐
imageQuery(query)
scaledImg
<-‐
scaleImg(img)
}
yield
NewPostData(text,
scaledImg)
Asynchronous
Asynchronous
Asynchronous
Asynchronous
“I am for you,
Alrik of Valt.”
6. Akka is Concurrency
Actors: Living objects with concurrent context
Futures: These aren’t Java’s Futures
val
futureData
=
for
{
response
<-‐
httpGet(…)
query
=
response.body.as[Query]
(img,
text)
<-‐
imageQuery(query)
scaledImg
<-‐
scaleImg(img)
}
yield
NewPostData(text,
scaledImg)
Asynchronous
Asynchronous
Asynchronous
Asynchronous
Streams: Async Non-Blocking and Back-Pressured
Source
Sink
Demand
Supply
Http too…
“I am for you,
Alrik of Valt.”
7. Akka is Concurrency
Actors: Living objects with concurrent context
Futures: These aren’t Java’s Futures
val
futureData
=
for
{
response
<-‐
httpGet(…)
query
=
response.body.as[Query]
(img,
text)
<-‐
imageQuery(query)
scaledImg
<-‐
scaleImg(img)
}
yield
NewPostData(text,
scaledImg)
Asynchronous
Asynchronous
Asynchronous
Asynchronous
Streams: Async Non-Blocking and Back-Pressured
Source
Sink
Demand
Supply
Http too…
“I am for you,
Alrik of Valt.”
Support for Scala and Java (but use Scala, cuz…)
10. Actors: Concurrency in Isolation
count: 2
alert: Y
score: 16
count: 4
alert: N
score: 2
count: 33
alert: G
score: 71
count: 13
alert: G
score: 12
count: 7
alert: X
score: 5
count: 8
alert: N
score: 11
count: 2
alert: I
score: 14
count: 87
alert: G
score: 0
count: 1
alert: B
score: 6
count: 7
alert: W
score: 32
count: 7
alert: O
score: 19
count: 4
alert: G
score: 99
count: _
alert: _
score: _
✗Construct as many as you’d like
11. Actors: Concurrency in Isolation
count: 2
alert: Y
score: 16
count: 4
alert: N
score: 2
count: 33
alert: G
score: 71
count: 13
alert: G
score: 12
count: 7
alert: X
score: 5
count: 8
alert: N
score: 11
count: 2
alert: I
score: 14
count: 87
alert: G
score: 0
count: 1
alert: B
score: 6
count: 7
alert: W
score: 32
count: 7
alert: O
score: 19
count: 4
alert: G
score: 99
count: _
alert: _
score: _
✗Construct as many as you’d like
✗Each one encapsulates its own state
12. Actors: Concurrency in Isolation
count: 2
alert: Y
score: 16
count: 4
alert: N
score: 2
count: 33
alert: G
score: 71
count: 13
alert: G
score: 12
count: 7
alert: X
score: 5
count: 8
alert: N
score: 11
count: 2
alert: I
score: 14
count: 87
alert: G
score: 0
count: 1
alert: B
score: 6
count: 7
alert: W
score: 32
count: 7
alert: O
score: 19
count: 4
alert: G
score: 99
Thread
Thread
count: _
alert: _
score: _
✗Construct as many as you’d like
✗Each one encapsulates its own state
✗They all (can) share the same thread pool
13. Actors: Concurrency in Isolation
count: 2
alert: Y
score: 16
count: 4
alert: N
score: 2
count: 33
alert: G
score: 71
count: 13
alert: G
score: 12
count: 7
alert: X
score: 5
count: 8
alert: N
score: 11
count: 2
alert: I
score: 14
count: 87
alert: G
score: 0
count: 1
alert: B
score: 6
count: 7
alert: W
score: 32
count: 7
alert: O
score: 19
count: 4
alert: G
score: 99
Thread
Thread
count: _
alert: _
score: _
✗Construct as many as you’d like
✗Each one encapsulates its own state
✗They all (can) share the same thread pool
✗They cannot interfere with each other
14. Actors: Concurrency in Isolation
count: 2
alert: Y
score: 16
count: 4
alert: N
score: 2
count: 33
alert: G
score: 71
count: 8
alert: N
score: 11
count: 2
alert: I
score: 14
count: 87
alert: G
score: 0
count: 1
alert: B
score: 6
count: 7
alert: W
score: 32
count: 7
alert: O
score: 19
count: 4
alert: G
score: 99
Thread
Thread
count: _
alert: _
score: _
✗Construct as many as you’d like
✗Each one encapsulates its own state
✗They all (can) share the same thread pool
✗They cannot interfere with each other
✗Their life-cycles are entirely under your control
16. It’s all about the messages!
Actors have no public methods⦿ A
17. It’s all about the messages!
Actors have no public methods⦿
Actors have no publicly accessible data⦿
A B
18. It’s all about the messages!
Actors have no public methods⦿
Actors have no publicly accessible data⦿
You cannot communicate with Actors
Synchronously
⦿
A B
19. It’s all about the messages!
Actors have no public methods⦿
Actors have no publicly accessible data⦿
You cannot communicate with Actors
Synchronously
⦿
The only way to talk to them is with
Messages
⦿
A B
hey
20. It’s all about the messages!
Actors have no public methods⦿
Actors have no publicly accessible data⦿
You cannot communicate with Actors
Synchronously
⦿
The only way to talk to them is with
Messages
⦿
The only way to access their data is with
Messages
⦿
A B
83
21. It’s all about the messages!
Actors have no public methods⦿
Actors have no publicly accessible data⦿
You cannot communicate with Actors
Synchronously
⦿
The only way to talk to them is with
Messages
⦿
The only way to access their data is with
Messages
⦿
Messages can (and should) carry
conversational state
⦿
A B
A
22. It’s all about the messages!
Actors have no public methods⦿
Actors have no publicly accessible data⦿
You cannot communicate with Actors
Synchronously
⦿
The only way to talk to them is with
Messages
⦿
The only way to access their data is with
Messages
⦿
Messages can (and should) carry
conversational state
⦿
A B
A
Done(a,b,c)
24. Actors are Fault Tolerant
Actors supervise their children Parent
Child Child Child
Mailbox
Mailbox
Mailbox Mailbox
25. Actors are Fault Tolerant
Actors supervise their children
Failed Actors are restarted (or stopped,
or resumed, or escalated) by their supervisors
Parent
Child Child Child
Mailbox
Mailbox
Mailbox Mailbox
26. Actors are Fault Tolerant
Actors supervise their children
Failed Actors are restarted (or stopped,
or resumed, or escalated) by their supervisors
Restarted Actors are given a fresh state
Parent
Child Child Child
Mailbox
Mailbox
Mailbox Mailbox
27. Actors are Fault Tolerant
Actors supervise their children
Failed Actors are restarted (or stopped,
or resumed, or escalated) by their supervisors
Restarted Actors are given a fresh state
The message they were processing is lost
Parent
Child Child Child
Mailbox
Mailbox
Mailbox Mailbox
28. Actors are Fault Tolerant
Actors supervise their children
Failed Actors are restarted (or stopped,
or resumed, or escalated) by their supervisors
Restarted Actors are given a fresh state
The message they were processing is lost
Parent
Child Child
Mailbox
Mailbox
Mailbox Mailbox
Child
30. Death is Actionable
❉ Restarting is invisible to outsiders…
❉ …But Actor Death is visible
❉ Deathwatch lets Actors react to death,
such as to recreate a child
Parent
Child ChildChild
Deathwatch
Mailbox
31. Death is Actionable
❉ Restarting is invisible to outsiders…
❉ …But Actor Death is visible
❉ Deathwatch lets Actors react to death,
such as to recreate a child
Parent
ChildChildChild
Deathwatch
Mailbox
32. Death is Actionable
❉ Restarting is invisible to outsiders…
❉ …But Actor Death is visible
❉ Deathwatch lets Actors react to death,
such as to recreate a child
Parent
ChildChildChild
Deathwatch
Mailbox
❉
… Or a transaction is complete, or it’s
time to shut down, or a current stage of
processing is finished, or…
33. Death is Actionable
❉ Restarting is invisible to outsiders…
❉ …But Actor Death is visible
❉ Deathwatch lets Actors react to death,
such as to recreate a child
Parent
ChildChildChild
Deathwatch
Mailbox
❉ Remember that this is death, so the
mailbox contents are lost
❉
… Or a transaction is complete, or it’s
time to shut down, or a current stage of
processing is finished, or…
35. So, why would I use Actors?
✗Actors help you manage concurrency
Reasoning
36. So, why would I use Actors?
✗Actors help you manage concurrency
✗Actors let you implement services within your system
Reasoning
Service decoupling
37. So, why would I use Actors?
✗Actors help you manage concurrency
✗Actors let you implement services within your system
✗Actors let you design an entirely asynchronous system
Reasoning
Service decoupling
Capacity and Throughput
38. So, why would I use Actors?
✗Actors help you manage concurrency
✗Actors let you implement services within your system
✗Actors let you design an entirely asynchronous system
✗Actors let you define the resiliency of your applications
Reasoning
Service decoupling
Capacity and Throughput
Fault Tolerance
39. So, why would I use Actors?
✗Actors help you manage concurrency
✗Actors let you implement services within your system
✗Actors let you design an entirely asynchronous system
✗Actors let you define the resiliency of your applications
✗
Eventual consistency, and message delivery failure are realities
that Actors help you deal with throughout your code
Reasoning
Service decoupling
Capacity and Throughput
Fault Tolerance
Massive Scale
Self Healing
40. So, why would I use Actors?
✗Actors help you manage concurrency
✗Actors let you implement services within your system
✗Actors let you design an entirely asynchronous system
✗Actors let you define the resiliency of your applications
✗
Eventual consistency, and message delivery failure are realities
that Actors help you deal with throughout your code
✗
Most importantly, Actors help you think about the problem differently and express
your solutions more creatively
Reasoning
Service decoupling
Capacity and Throughput
Fault Tolerance
Massive Scale
Self Healing
Sanity, Clarity, and Reasonability!!
43. “Functional” Futures
◎ A Future is just a value, but not yet…
◎
java.util.concurrent.Future is a bad Future.
Akka gave us Futures that compose!
44. “Functional” Futures
◎ A Future is just a value, but not yet…
◎
java.util.concurrent.Future is a bad Future.
Akka gave us Futures that compose!
◎
Composable Futures let us abstract over Future
values, rather than wait for them
for {
45. “Functional” Futures
◎ A Future is just a value, but not yet…
◎
java.util.concurrent.Future is a bad Future.
Akka gave us Futures that compose!
◎
Composable Futures let us abstract over Future
values, rather than wait for them
for {
a <- futureA()
futureA()
46. futureB(a)
“Functional” Futures
◎ A Future is just a value, but not yet…
◎
java.util.concurrent.Future is a bad Future.
Akka gave us Futures that compose!
◎
Composable Futures let us abstract over Future
values, rather than wait for them
for {
a <- futureA()
b <- futureB(a)
futureA()
47. futureC(a,b) futureB(a)
“Functional” Futures
◎ A Future is just a value, but not yet…
◎
java.util.concurrent.Future is a bad Future.
Akka gave us Futures that compose!
◎
Composable Futures let us abstract over Future
values, rather than wait for them
for {
a <- futureA()
b <- futureB(a)
c <- futureC(a,b)
futureA()
48. futureC(a,b) futureB(a)
“Functional” Futures
◎ A Future is just a value, but not yet…
◎
java.util.concurrent.Future is a bad Future.
Akka gave us Futures that compose!
◎
Composable Futures let us abstract over Future
values, rather than wait for them
for {
a <- futureA()
b <- futureB(a)
c <- futureC(a,b)
} yield c
futureA()
One
composed
Future
49. futureC(a,b) futureB(a)
“Functional” Futures
◎ A Future is just a value, but not yet…
◎
java.util.concurrent.Future is a bad Future.
Akka gave us Futures that compose!
◎
Composable Futures let us abstract over Future
values, rather than wait for them
for {
a <- futureA()
b <- futureB(a)
c <- futureC(a,b)
} yield c
futureA()
◎
Futures compose as Monads compose, which makes them “standard”
functional abstractions, and that’s a powerful thing
One
composed
Future
51. Abolish Callback Hell
public void restHandler(RESTRequest req) {
idservice.validate(req.userInfo, new Callback<ValidateResult>() {
public void run(ValidateResult result) {
if (result.isValid) {
db.getProfile(req.userId, new Callback<UserProfile>() {
public void run(UserProfile profile) {
picServer.get(profile.pic1, new Callback<Pic>() {
public void run(Pic p1) {
picServer.get(profile.pic2, new Callback<Pic>() {
public void run(Pic p2) {
picServer.get(profile.pic3, new Callback<Pic>() {
public void run(Pic p3) {
picServer.get(profile.pic4, new Callback<Pic>() {
public void run(Pic p4) {
picServer.get(profile.pic5, new Callback<Pic>() {
public void run(Pic p5) {
twitterServer.getRecentActivity(req.userInfo, new Callback<TwitterActivity>() {
public void run(TwitterActivity activity) {
req.sendResponse(pic1, pic2, pic3, pic4, pic5, activity)
}
}
}
}
}
}
}
}
52. Abolish Callback Hell
public void restHandler(RESTRequest req) {
idservice.validate(req.userInfo, new Callback<ValidateResult>() {
public void run(ValidateResult result) {
if (result.isValid) {
db.getProfile(req.userId, new Callback<UserProfile>() {
public void run(UserProfile profile) {
picServer.get(profile.pic1, new Callback<Pic>() {
public void run(Pic p1) {
picServer.get(profile.pic2, new Callback<Pic>() {
public void run(Pic p2) {
picServer.get(profile.pic3, new Callback<Pic>() {
public void run(Pic p3) {
picServer.get(profile.pic4, new Callback<Pic>() {
public void run(Pic p4) {
picServer.get(profile.pic5, new Callback<Pic>() {
public void run(Pic p5) {
twitterServer.getRecentActivity(req.userInfo, new Callback<TwitterActivity>() {
public void run(TwitterActivity activity) {
req.sendResponse(pic1, pic2, pic3, pic4, pic5, activity)
}
}
}
}
}
}
}
}
We didn’t handle errors
We didn’t handle timeouts
It’s not necessarily Threadsafe
It’s incredibly hard to read
56. So why would I use Futures?
Asynchronous programming is still hard⦿
57. So why would I use Futures?
Asynchronous programming is still hard⦿
Programming synchronously isn’t a reasonable response⦿
Thread starvation
timeouts
capacity issues
thread thrashing
58. So why would I use Futures?
Asynchronous programming is still hard⦿
Programming synchronously isn’t a reasonable response⦿
Scala Futures embody asynchronous values⦿
Thread starvation
timeouts
capacity issues
thread thrashing
Everything is a value
59. So why would I use Futures?
Asynchronous programming is still hard⦿
Programming synchronously isn’t a reasonable response⦿
Scala Futures embody asynchronous values⦿
They let us express composed asynchronous computation⦿
Thread starvation
timeouts
capacity issues
thread thrashing
Everything is a value
Less Side Effects
60. So why would I use Futures?
Asynchronous programming is still hard⦿
Programming synchronously isn’t a reasonable response⦿
Scala Futures embody asynchronous values⦿
They let us express composed asynchronous computation⦿
Futures let us propagate errors and recover from them⦿
Thread starvation
timeouts
capacity issues
thread thrashing
Everything is a value
Less Side Effects
Graceful Failure
Resiliency
61. So why would I use Futures?
Asynchronous programming is still hard⦿
Programming synchronously isn’t a reasonable response⦿
Scala Futures embody asynchronous values⦿
They let us express composed asynchronous computation⦿
Futures let us propagate errors and recover from them⦿
Asynchronous programming has always been possible but
Futures now make it much more viable
⦿
Thread starvation
timeouts
capacity issues
thread thrashing
Everything is a value
Less Side Effects
Graceful Failure
Resiliency
63. Operating on Data Streams
❉ In the real world, we communicate with things
Networks
Disks
Databases Services Slower Algorithms
64. Operating on Data Streams
❉ In the real world, we communicate with things
Networks
Disks
Databases Services Slower Algorithms
❉ Polling sucks. We live in a real time world.
65. Operating on Data Streams
❉ In the real world, we communicate with things
Networks
Disks
Databases Services Slower Algorithms
❉ Polling sucks. We live in a real time world.
❉ Eventing can be hard, since it doesn’t compose
66. Operating on Data Streams
❉ In the real world, we communicate with things
Networks
Disks
Databases Services Slower Algorithms
❉ Polling sucks. We live in a real time world.
❉ Eventing can be hard, since it doesn’t compose
❉ Throttling is a real problem we never address
67. Operating on Data Streams
❉ In the real world, we communicate with things
Networks
Disks
Databases Services Slower Algorithms
❉ Polling sucks. We live in a real time world.
❉ Eventing can be hard, since it doesn’t compose
❉ Throttling is a real problem we never address
❉ Akka Streams help us solve all of these problems
68. Operating on Data Streams
❉ In the real world, we communicate with things
Networks
Disks
Databases Services Slower Algorithms
❉ Polling sucks. We live in a real time world.
❉ Eventing can be hard, since it doesn’t compose
❉ Throttling is a real problem we never address
❉ Akka Streams help us solve all of these problems
Source
Transformation
Flow
Transformation
Flow
Sink
Demand
Supply
71. BackPressure is key
◎ Fast producers can kill; we only have so much RAM
◎ Producers can’t be artificially slow just to be nice
Source
Sink
72. BackPressure is key
◎ Fast producers can kill; we only have so much RAM
◎ Producers can’t be artificially slow just to be nice
◎ Consumers signal demand, Producers signal supply
Source
Sink
73. BackPressure is key
◎ Fast producers can kill; we only have so much RAM
◎ Producers can’t be artificially slow just to be nice
◎ Consumers signal demand, Producers signal supply
◎ When a consumer is slow, it signals no demand
Source
Sink
74. BackPressure is key
◎ Fast producers can kill; we only have so much RAM
◎ Producers can’t be artificially slow just to be nice
◎ Consumers signal demand, Producers signal supply
◎ When a consumer is slow, it signals no demand
◎ When a producer is slow, it doesn’t supply
Source
Sink
75. BackPressure is key
◎ Fast producers can kill; we only have so much RAM
◎ Producers can’t be artificially slow just to be nice
◎ Consumers signal demand, Producers signal supply
◎ When a consumer is slow, it signals no demand
◎ When a producer is slow, it doesn’t supply
Source
Sink Supply
79. Composable Binary Protocols
Framer
ByteString ByteString
BidiFlow
Serializer
Object ByteString
BidiFlow
Chunker
ByteString ByteString
BidiFlow
Application
Object Object
Source Sink
Network
ByteString ByteString
Source Sink
BidiFlow
ByteStringObject
✗Entirely reusable components that fit in any BiDirectional Flow
80. Composable Binary Protocols
Framer
ByteString ByteString
BidiFlow
Serializer
Object ByteString
BidiFlow
Chunker
ByteString ByteString
BidiFlow
Application
Object Object
Source Sink
Network
ByteString ByteString
Source Sink
BidiFlow
ByteStringObject
✗Entirely reusable components that fit in any BiDirectional Flow
✗Type safe (or as type safe as byte string marshaling gets)
81. Composable Binary Protocols
Framer
ByteString ByteString
BidiFlow
Serializer
Object ByteString
BidiFlow
Chunker
ByteString ByteString
BidiFlow
Application
Object Object
Source Sink
Network
ByteString ByteString
Source Sink
BidiFlow
ByteStringObject
✗Entirely reusable components that fit in any BiDirectional Flow
✗Type safe (or as type safe as byte string marshaling gets)
✗Entirely back pressured from end to end
82. Composable Binary Protocols
Framer
ByteString ByteString
BidiFlow
Serializer
Object ByteString
BidiFlow
Chunker
ByteString ByteString
BidiFlow
Application
Object Object
Source Sink
Network
ByteString ByteString
Source Sink
BidiFlow
ByteStringObject
✗Entirely reusable components that fit in any BiDirectional Flow
✗Type safe (or as type safe as byte string marshaling gets)
✗Entirely back pressured from end to end
✗100% event driven and reactive Realtime Speeds
No Blocking Threads
Natural Throttling
graceful performance degradationNot a Crash
84. Why Would I use Streams?
Streaming is (probably) the crown jewel of Akka’s offering (but it’s a tough call)
85. Why Would I use Streams?
Streaming is (probably) the crown jewel of Akka’s offering
The need to respond to backpressure is real and we never do it !
(but it’s a tough call)
86. Why Would I use Streams?
Streaming is (probably) the crown jewel of Akka’s offering
The need to respond to backpressure is real and we never do it
The need to treat our threads with respect is important
!
!
(but it’s a tough call)
87. Why Would I use Streams?
Streaming is (probably) the crown jewel of Akka’s offering
The need to respond to backpressure is real and we never do it
The need to treat our threads with respect is important
The need to be reactive and fast is vital to the user experience
!
!
!
(but it’s a tough call)
88. Why Would I use Streams?
Streaming is (probably) the crown jewel of Akka’s offering
The need to respond to backpressure is real and we never do it
The need to treat our threads with respect is important
The need to be reactive and fast is vital to the user experience
Streams give us all of this and let us use our hardware to its fullest
!
!
!
!!!
(but it’s a tough call)
90. Akka from 20k feetAkka from 20k feet
Actors!
Actors!
Live Objects
Supervised
Asynchronous
Message Passing
Services
State Machines
Network Ready
91. Akka from 20k feetAkka from 20k feet
Actors!
Actors!
Futures!
Futures!
Live Objects
Supervised
Asynchronous
Message Passing
Services
State Machines
Network Ready
Composable Values
Reactive
Monadic
Immutable
Threadsafe
Work Well with Actors
92. Akka from 20k feetAkka from 20k feet
Actors!
Actors!
Futures!
Futures!
Streams!
Streams!
Live Objects
Supervised
Asynchronous
Message Passing
Services
State Machines
Network Ready
Composable Values
Reactive
Monadic
Immutable
Threadsafe
Work Well with Actors
BackPressured
Composable
Reusable
Event Driven
Flexible
Lots of Activity and Support
Work with Futures and Actors
93. Go Get AKKA!Go Get AKKA!
Website: http://akka.io
Scala Reference: http://doc.akka.io/docs/akka/current/scala.html
Java Reference: http://doc.akka.io/docs/akka/current/java.html
Streams Reference: http://doc.akka.io/docs/akka-stream-and-http-experimental/current/scala.html
Derek Wyatt
Twitter: @derekwyatt
Email: derek@derekwyatt.orgAugust 2015