3. 3
Apps in the 60s-90s
were written for
Apps today
are written for
4. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines
5. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
6. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors
7. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
8. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM
9. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
10. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk
11. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
12. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks
13. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks Fast networks
14. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks Fast networks
Few concurrent users
15. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks Fast networks
Few concurrent users Lots of concurrent users
16. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks Fast networks
Few concurrent users Lots of concurrent users
Small data sets
17. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks Fast networks
Few concurrent users Lots of concurrent users
Small data sets Large data sets
18. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks Fast networks
Few concurrent users Lots of concurrent users
Small data sets Large data sets
Latency in seconds
19. 3
Apps in the 60s-90s
were written for
Apps today
are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks Fast networks
Few concurrent users Lots of concurrent users
Small data sets Large data sets
Latency in seconds Latency in milliseconds
25. Event-Driven
• Loosely coupled architecture, easier to extend, maintain, evolve
• Asynchronous and non-blocking
• Concurrent by design, immutable state
• Lower latency and higher throughput
8
“Clearly, the goal is to do these operations concurrently and
non-blocking, so that entire blocks of seats or sections are not locked.
We’re able to find and allocate seats under load in less than 20ms
without trying very hard to achieve it.”
Andrew Headrick, Platform Architect, Ticketfly
32. 10
A computational model that embodies:
✓ Processing
✓ Storage
✓ Communication
Supports 3 axioms—when an Actor receives a message it can:
The Actor Model
33. 10
A computational model that embodies:
✓ Processing
✓ Storage
✓ Communication
Supports 3 axioms—when an Actor receives a message it can:
1. Create new Actors
The Actor Model
34. 10
A computational model that embodies:
✓ Processing
✓ Storage
✓ Communication
Supports 3 axioms—when an Actor receives a message it can:
1. Create new Actors
2. Send messages to Actors it knows
The Actor Model
35. 10
A computational model that embodies:
✓ Processing
✓ Storage
✓ Communication
Supports 3 axioms—when an Actor receives a message it can:
1. Create new Actors
2. Send messages to Actors it knows
3. Designate how it should handle the next message it receives
The Actor Model
36. The essence of an actor
from Akka’s perspective
0. DEFINE
1. CREATE
2. SEND
3. BECOME
4. SUPERVISE
11
37. public class Greeting implements Serializable {
public final String who;
public Greeting(String who) { this.who = who; }
}
!
public class Greeter extends AbstractActor {{
receive(ReceiveBuilder.
match(Greeting.class, m -> {
println(“Hello " + m.who);
}).
matchAny(unknown -> {
println(“Unknown message " + unknown);
}).build());
}}
0. DEFINE
12
38. public class Greeting implements Serializable {
public final String who;
public Greeting(String who) { this.who = who; }
}
!
public class Greeter extends AbstractActor {{
receive(ReceiveBuilder.
match(Greeting.class, m -> {
println(“Hello " + m.who);
}).
matchAny(unknown -> {
println(“Unknown message " + unknown);
}).build());
}}
0. DEFINE
12
Define the message(s) the Actor
should be able to respond to
39. public class Greeting implements Serializable {
public final String who;
public Greeting(String who) { this.who = who; }
}
!
public class Greeter extends AbstractActor {{
receive(ReceiveBuilder.
match(Greeting.class, m -> {
println(“Hello " + m.who);
}).
matchAny(unknown -> {
println(“Unknown message " + unknown);
}).build());
}}
0. DEFINE
12
Define the message(s) the Actor
should be able to respond to
Define the Actor class
40. public class Greeting implements Serializable {
public final String who;
public Greeting(String who) { this.who = who; }
}
!
public class Greeter extends AbstractActor {{
receive(ReceiveBuilder.
match(Greeting.class, m -> {
println(“Hello " + m.who);
}).
matchAny(unknown -> {
println(“Unknown message " + unknown);
}).build());
}}
0. DEFINE
12
Define the message(s) the Actor
should be able to respond to
Define the Actor class
Define the Actor’s behavior
42. ActorSystem system = ActorSystem.create("MySystem");
!
ActorRef greeter =
system.actorOf(Props.create(Greeter.class), “greeter");
1. CREATE
Create an Actor system
43. ActorSystem system = ActorSystem.create("MySystem");
!
ActorRef greeter =
system.actorOf(Props.create(Greeter.class), “greeter");
1. CREATE
Create an Actor system
Actor configuration
44. ActorSystem system = ActorSystem.create("MySystem");
!
ActorRef greeter =
system.actorOf(Props.create(Greeter.class), “greeter");
Give it a name
1. CREATE
Create an Actor system
Actor configuration
45. ActorSystem system = ActorSystem.create("MySystem");
!
ActorRef greeter =
system.actorOf(Props.create(Greeter.class), “greeter");
Give it a name
1. CREATE
Create the Actor
Create an Actor system
Actor configuration
46. ActorSystem system = ActorSystem.create("MySystem");
!
ActorRef greeter =
system.actorOf(Props.create(Greeter.class), “greeter");
Give it a name
1. CREATE
Create the Actor
You get an ActorRef back
Create an Actor system
Actor configuration
70. Resilient
• Failure is embraced as a natural state in the app lifecycle
• Resilience is a first-class construct
• Failure is detected, isolated, and managed
• Applications self heal
20
“The Typesafe Reactive Platform helps us maintain a very
aggressive development and deployment cycle, all in a fail-forward manner.
It’s now the default choice for developing all new services.”
Peter Hausel, VP Engineering, Gawker Media
98. 4. SUPERVISE
28
class Supervisor extends UntypedActor {
private SupervisorStrategy strategy = new OneForOneStrategy(
10, Duration.create(1, TimeUnit.MINUTES),
DeciderBuilder.
match(ArithmeticException.class, e -> resume()).
match(NullPointerException.class, e -> restart()).
matchAny( e -> escalate()).
build());
!
@Override public SupervisorStrategy supervisorStrategy() {
return strategy;
}
Every single actor has a default supervisor strategy.
Which is usually sufficient.
But it can be overridden.
99. 4. SUPERVISE
28
class Supervisor extends UntypedActor {
private SupervisorStrategy strategy = new OneForOneStrategy(
10, Duration.create(1, TimeUnit.MINUTES),
DeciderBuilder.
match(ArithmeticException.class, e -> resume()).
match(NullPointerException.class, e -> restart()).
matchAny( e -> escalate()).
build());
!
@Override public SupervisorStrategy supervisorStrategy() {
return strategy;
}
ActorRef worker = context.actorOf(
Props.create(Worker.class), "worker");
public void onReceive(Object i) throws Exception {
…
}
}
100. Monitor through Death Watch
29
public class WatchActor extends AbstractActor {
final ActorRef child = context().actorOf(Props.empty(), "child");
!
public WatchActor() {
context().watch(child);
receive(ReceiveBuilder.
match(Terminated.class,
t -> t.actor().equals(child),
t -> {
… // handle termination
}).build()
);
}
}
101. Monitor through Death Watch
29
public class WatchActor extends AbstractActor {
final ActorRef child = context().actorOf(Props.empty(), "child");
!
public WatchActor() {
context().watch(child);
receive(ReceiveBuilder.
match(Terminated.class,
t -> t.actor().equals(child),
t -> {
… // handle termination
}).build()
);
}
}
Create a child actor
102. Monitor through Death Watch
29
public class WatchActor extends AbstractActor {
final ActorRef child = context().actorOf(Props.empty(), "child");
!
public WatchActor() {
context().watch(child);
receive(ReceiveBuilder.
match(Terminated.class,
t -> t.actor().equals(child),
t -> {
… // handle termination
}).build()
);
}
}
Create a child actor
Watch it
103. Monitor through Death Watch
29
public class WatchActor extends AbstractActor {
final ActorRef child = context().actorOf(Props.empty(), "child");
!
public WatchActor() {
context().watch(child);
receive(ReceiveBuilder.
match(Terminated.class,
t -> t.actor().equals(child),
t -> {
… // handle termination
}).build()
);
}
}
Create a child actor
Watch it
Handle termination message
105. Scalable
• Scalability and elasticity to embrace the Cloud
• Leverage all cores via asynchronous programming
• Clustered servers support joining and leaving of nodes
• More cost-efficient utilization of hardware
31
“Our traffic can increase by as much as 100x for 15 minutes each day.
Until a couple of years ago, noon was a stressful time.
Nowadays, it’s usually a non-event.”
Eric Bowman, VP Architecture, Gilt Groupe
106. Define a router
32
ActorRef router = context().actorOf(
new RoundRobinPool(5).props(Props.create(Worker.class)),
“router”)
112. • Supports two different models:
• Command Sourcing — at least once
• Event Sourcing — at most once
• Great for implementing
• durable actors
• replication
• CQRS etc.
• Messages persisted to Journal and replayed on restart
37
Use Akka Persistence
116. 38
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery
as normal operation
117. 38
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery
as normal operation
only state-changing behavior
during recovery
118. 38
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery
as normal operation
only state-changing behavior
during recovery
persisted before validation
119. 38
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery
as normal operation
only state-changing behavior
during recovery
persisted before validation events cannot fail
120. 38
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery
as normal operation
only state-changing behavior
during recovery
persisted before validation events cannot fail
allows retroactive changes to
the business logic
121. 38
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery
as normal operation
only state-changing behavior
during recovery
persisted before validation events cannot fail
allows retroactive changes to
the business logic
fixing the business logic will not
affect persisted events
122. 38
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery
as normal operation
only state-changing behavior
during recovery
persisted before validation events cannot fail
allows retroactive changes to
the business logic
fixing the business logic will not
affect persisted events
naming: represent intent,
imperative
123. 38
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery
as normal operation
only state-changing behavior
during recovery
persisted before validation events cannot fail
allows retroactive changes to
the business logic
fixing the business logic will not
affect persisted events
naming: represent intent,
imperative
naming: things that have
completed, verbs in past tense
124. Akka
Persistence
Webinar
Life beyond Distributed Transactions:
an Apostate’s Opinion
Position Paper by Pat Helland
“In general, application developers simply do not implement
large scalable applications assuming distributed transactions.”
Pat Helland
http://www-‐db.cs.wisc.edu/cidr/cidr2007/papers/cidr07p15.pdf
125. Akka
Persistence
Webinar
Consistency boundary
• Aggregate Root is the Transactional Boundary
• Strong consistency within an Aggregate
• Eventual consistency between Aggregates
• No limit to scalability
126. Akka
Persistence
Webinar
Domain Events
• Things that have completed, facts
• Immutable
• Verbs in past tense
• CustomerRelocated
• CargoShipped
• InvoiceSent
“State transitions are an important part of our problem
space and should be modeled within our domain.”
Greg Young, 2008
128. Responsive
• Real-time, engaging, rich and collaborative
• Create an open and ongoing dialog with users
• More efficient workflow; inspires a feeling of connectedness
• Fully Reactive enabling push instead of pull
43
“The move to these technologies is already paying off.
Response times are down for processor intensive code–such as image
and PDF generation–by around 75%.”
Brian Pugh, VP of Engineering, Lucid Software