Slide 1

Slide 1 text

Go Reactive Event-Driven, Scalable, Resilient & Responsive Systems Jonas Bonér CTO Typesafe @jboner

Slide 2

Slide 2 text

New Tools for a New Era • The demands and expectations for applications have changed dramatically in recent years

Slide 3

Slide 3 text

New Tools for a New Era • The demands and expectations for applications have changed dramatically in recent years • We need to write applications that manages 1. Mobile devices 2. Multicore architectures 3. Cloud computing environments

Slide 4

Slide 4 text

New Tools for a New Era • The demands and expectations for applications have changed dramatically in recent years • We need to write applications that manages 1. Mobile devices 2. Multicore architectures 3. Cloud computing environments • Deliver applications that are 1. Interactive & Real-time 2. Responsive 3. Collaborative

Slide 5

Slide 5 text

New Tools for a New Era

Slide 6

Slide 6 text

We to need to build systems that: New Tools for a New Era

Slide 7

Slide 7 text

We to need to build systems that: • react to events — Event-Driven New Tools for a New Era

Slide 8

Slide 8 text

We to need to build systems that: • react to events — Event-Driven • react to load — Scalable New Tools for a New Era

Slide 9

Slide 9 text

We to need to build systems that: • react to events — Event-Driven • react to load — Scalable • react to failure — Resilient New Tools for a New Era

Slide 10

Slide 10 text

We to need to build systems that: • react to events — Event-Driven • react to load — Scalable • react to failure — Resilient • react to users — Responsive New Tools for a New Era

Slide 11

Slide 11 text

Reactive Applications We to need to build systems that: • react to events — Event-Driven • react to load — Scalable • react to failure — Resilient • react to users — Responsive New Tools for a New Era

Slide 12

Slide 12 text

Reactive “Readily responsive to a stimulus” - Merriam Webster

Slide 13

Slide 13 text

The four traits of Reactive Responsive Event-Driven Scalable Resilient

Slide 14

Slide 14 text

Event-Driven “The flow of the program is determined by events” - Wikipedia

Slide 15

Slide 15 text

Shared mutable state

Slide 16

Slide 16 text

Shared mutable state Together with threads...

Slide 17

Slide 17 text

Shared mutable state ...leads to Together with threads...

Slide 18

Slide 18 text

Shared mutable state ...code that is totally non-deterministic ...leads to Together with threads...

Slide 19

Slide 19 text

Shared mutable state ...code that is totally non-deterministic ...and the root of all EVIL ...leads to Together with threads...

Slide 20

Slide 20 text

Shared mutable state ...code that is totally non-deterministic ...and the root of all EVIL ...leads to Together with threads... Please, avoid it at all cost

Slide 21

Slide 21 text

Shared mutable state ...code that is totally non-deterministic ...and the root of all EVIL ...leads to Together with threads... Please, avoid it at all cost

Slide 22

Slide 22 text

1. Never block

Slide 23

Slide 23 text

1. Never block • ...unless you really have to • Blocking kills scalability (& performance) • Never sit on resources you don’t use • Use non-blocking IO • Use lock-free concurrency

Slide 24

Slide 24 text

2. Go Async Design for reactive event-driven systems • Use asynchronous event/message passing • Think in workflow, how the events flow in the system • Gives you 1. lower latency 2. better throughput 3. a more loosely coupled architecture, easier to extend, evolve & maintain

Slide 25

Slide 25 text

Amdahl’s Law

Slide 26

Slide 26 text

Amdahl’s Law Needs to be Reactive from TOP to BOTTOM

Slide 27

Slide 27 text

You deserve better tools • Actors • Agents • Futures/Dataflow • Reactive Extensions (Rx)

Slide 28

Slide 28 text

Actors • Share NOTHING • Isolated lightweight event-based processes • Each actor has a mailbox (message queue) • Communicates through asynchronous & non-blocking message passing • Location transparent (distributable) • Supervision-based failure management • Examples: Akka & Erlang

Slide 29

Slide 29 text

public class Greeting implements Serializable { public final String who; public Greeting(String who) { this.who = who; } } ! public class GreetingActor extends UntypedActor { ! public void onReceive(Object message) { if (message instanceof Greeting) println("Hello " + ((Greeting) message).who); } } Actors in Akka

Slide 30

Slide 30 text

public class Greeting implements Serializable { public final String who; public Greeting(String who) { this.who = who; } } ! public class GreetingActor extends UntypedActor { ! public void onReceive(Object message) { if (message instanceof Greeting) println("Hello " + ((Greeting) message).who); } } Actors in Akka Define the message(s) the Actor should be able to respond to

Slide 31

Slide 31 text

public class Greeting implements Serializable { public final String who; public Greeting(String who) { this.who = who; } } ! public class GreetingActor extends UntypedActor { ! public void onReceive(Object message) { if (message instanceof Greeting) println("Hello " + ((Greeting) message).who); } } Define the Actor class Actors in Akka Define the message(s) the Actor should be able to respond to

Slide 32

Slide 32 text

public class Greeting implements Serializable { public final String who; public Greeting(String who) { this.who = who; } } ! public class GreetingActor extends UntypedActor { ! public void onReceive(Object message) { if (message instanceof Greeting) println("Hello " + ((Greeting) message).who); } } Define the Actor class Define the Actor’s behavior Actors in Akka Define the message(s) the Actor should be able to respond to

Slide 33

Slide 33 text

• Reactive memory cells • Send a update function to the Agent, which 1. adds it to an (ordered) queue, to be 2. applied to the Agent async & non-blocking • Reads are “free”, just dereferences the Ref • Composes nicely • Examples: Clojure & Akka Agents

Slide 34

Slide 34 text

val agent = Agent(5) agent send (x => x + 1) agent send (x => x * 2) Agents in Akka

Slide 35

Slide 35 text

• Allows you to spawn concurrent computations and work with the not yet computed results • Write-once, Read-many • Freely sharable • Allows non-blocking composition • Monadic (composes in for-comprehensions) • Build in model for managing failure Futures/Dataflow

Slide 36

Slide 36 text

val result1 = future { ... } val result2 = future { ... } val result3 = future { ... } ! val sum = for { r1 <- result1 r2 <- result2 r3 <- result3 } yield { r1 + r2 + r3 } Futures in Scala

Slide 37

Slide 37 text

• Extend Futures with the concept of a Stream • Composable in a type-safe way • Event-based & asynchronous • Observable ⇛ Push Collections • onNext(T), onError(E), onCompleted() • Compared to Iterable ⇛ Pull Collections • Examples: Rx.NET, RxJava, RxJS etc. Reactive Extensions (Rx)

Slide 38

Slide 38 text

getDataFromNetwork() .skip(10) .take(5) .map({ s -> return s + " transformed" }) .subscribe({ println "onNext => " + it }) RxJava

Slide 39

Slide 39 text

Scalable “Capable of being easily expanded or upgraded on demand” - Merriam Webster

Slide 40

Slide 40 text

Distributed systems is the new normal

Slide 41

Slide 41 text

Distributed systems is the new normal You already have a distributed system, whether you want it or not

Slide 42

Slide 42 text

Distributed systems is the new normal You already have a distributed system, whether you want it or not Mobile NOSQL DBs SQL Replication Cloud Services

Slide 43

Slide 43 text

What is the essence of distributed computing?

Slide 44

Slide 44 text

What is the essence of distributed computing? 1. Information travels at the speed of light 2. Independent things fail independently It’s to try to overcome that

Slide 45

Slide 45 text

Why do we need it?

Slide 46

Slide 46 text

Why do we need it? Scalability When you outgrow the resources of a single node

Slide 47

Slide 47 text

Why do we need it? Scalability When you outgrow the resources of a single node Availability Providing resilience if one node fails

Slide 48

Slide 48 text

Why do we need it? Scalability When you outgrow the resources of a single node Availability Providing resilience if one node fails Rich stateful clients

Slide 49

Slide 49 text

The problem?

Slide 50

Slide 50 text

It is still Very Hard The problem?

Slide 51

Slide 51 text

Slow node ! Dead node No difference and a Between a

Slide 52

Slide 52 text

The network is Inherently Unreliable

Slide 53

Slide 53 text

The network is Inherently Unreliable http://aphyr.com/posts/288-the-network-is-reliable

Slide 54

Slide 54 text

Fallacies Peter Deutsch’s 8 Fallacies of Distributed Computing

Slide 55

Slide 55 text

Fallacies 1. The network is reliable 2. Latency is zero 3. Bandwidth is infinite 4. The network is secure 5. Topology doesn't change 6. There is one administrator 7. Transport cost is zero 8. The network is homogeneous Peter Deutsch’s 8 Fallacies of Distributed Computing

Slide 56

Slide 56 text

Graveyard of distributed systems • Distributed Shared Mutable State • EVIL (where N is number of nodes) N

Slide 57

Slide 57 text

Graveyard of distributed systems • Distributed Shared Mutable State • EVIL (where N is number of nodes) N • Serializable Distributed Transactions

Slide 58

Slide 58 text

Graveyard of distributed systems • Distributed Shared Mutable State • EVIL (where N is number of nodes) N • Serializable Distributed Transactions • Synchronous RPC

Slide 59

Slide 59 text

Graveyard of distributed systems • Distributed Shared Mutable State • EVIL (where N is number of nodes) N • Serializable Distributed Transactions • Synchronous RPC • Guaranteed Delivery

Slide 60

Slide 60 text

Graveyard of distributed systems • Distributed Shared Mutable State • EVIL (where N is number of nodes) N • Serializable Distributed Transactions • Synchronous RPC • Guaranteed Delivery • Distributed Objects

Slide 61

Slide 61 text

Graveyard of distributed systems • Distributed Shared Mutable State • EVIL (where N is number of nodes) N • Serializable Distributed Transactions • Synchronous RPC • Guaranteed Delivery • Distributed Objects • “Sucks like an inverted hurricane” - Martin Fowler

Slide 62

Slide 62 text

Instead

Slide 63

Slide 63 text

Embrace the Network Instead and be done with it Use Asynchronous Message Passing

Slide 64

Slide 64 text

We need Location Transparency

Slide 65

Slide 65 text

// send message to local actor ActorRef localGreeter = system.actorOf( new Props(GreetingActor.class), “greeter"); ! localGreeter.tell(“Jonas”); What is Location Transparency?

Slide 66

Slide 66 text

// send message to local actor ActorRef localGreeter = system.actorOf( new Props(GreetingActor.class), “greeter"); ! localGreeter.tell(“Jonas”); What is Location Transparency? // send message to remote actor ActorRef remoteGreeter = system.actorOf( new Props(GreetingActor.class), “greeter"); ! remoteGreeter.tell(“Jonas”);

Slide 67

Slide 67 text

// send message to local actor ActorRef localGreeter = system.actorOf( new Props(GreetingActor.class), “greeter"); ! localGreeter.tell(“Jonas”); What is Location Transparency? // send message to remote actor ActorRef remoteGreeter = system.actorOf( new Props(GreetingActor.class), “greeter"); ! remoteGreeter.tell(“Jonas”); No difference

Slide 68

Slide 68 text

Partition for scale Replicate for resilience Divide & Conquer

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

Share Nothing

Slide 71

Slide 71 text

Asynchronous Communication Share Nothing

Slide 72

Slide 72 text

Asynchronous Communication Share Nothing Loose Coupling

Slide 73

Slide 73 text

Location Transparency Asynchronous Communication Share Nothing Loose Coupling

Slide 74

Slide 74 text

Location Transparency Asynchronous Communication Share Nothing No limit to scalability Loose Coupling

Slide 75

Slide 75 text

Location Transparency Asynchronous Communication Share Nothing No limit to scalability Loose Coupling Close to at least

Slide 76

Slide 76 text

Resilience “The ability of a substance or object to spring back into shape.” “The capacity to recover quickly from difficulties.” - Merriam Webster

Slide 77

Slide 77 text

Failure Recovery in Java/C/C# etc.

Slide 78

Slide 78 text

• You are given a SINGLE thread of control • If this thread blows up you are screwed • So you need to do all explicit error handling WITHIN this single thread • To make things worse - errors do not propagate between threads so there is NO WAY OF EVEN FINDING OUT that something have failed • This leads to DEFENSIVE programming with: • Error handling TANGLED with business logic • SCATTERED all over the code base Failure Recovery in Java/C/C# etc.

Slide 79

Slide 79 text

• You are given a SINGLE thread of control • If this thread blows up you are screwed • So you need to do all explicit error handling WITHIN this single thread • To make things worse - errors do not propagate between threads so there is NO WAY OF EVEN FINDING OUT that something have failed • This leads to DEFENSIVE programming with: • Error handling TANGLED with business logic • SCATTERED all over the code base Failure Recovery in Java/C/C# etc. We can do BETTER!!!

Slide 80

Slide 80 text

No content

Slide 81

Slide 81 text

The Right Way

Slide 82

Slide 82 text

• Isolate the failure • Compartmentalize • Manage failure locally • Avoid cascading failures The Right Way

Slide 83

Slide 83 text

• Isolate the failure • Compartmentalize • Manage failure locally • Avoid cascading failures The Right Way Use Bulkheads

Slide 84

Slide 84 text

...together with supervision

Slide 85

Slide 85 text

...together with supervision 1. Use Isolated lightweight processes (compartments) 2. Supervise these processes 1. Each process has a supervising parent process 2. Errors are reified and sent as (async) events to the supervisor 3. Supervisor manages the failure - can kill, restart, suspend/resume • Same semantics local as remote • Full decoupling between business logic & error handling • Build into the Actor model

Slide 86

Slide 86 text

Supervision in Akka Every single actor has a default supervisor strategy. Which is usually sufficient. But it can be overridden.

Slide 87

Slide 87 text

class Supervisor extends UntypedActor { private SupervisorStrategy strategy = new OneForOneStrategy( 10, Duration.parse("1 minute"), new Function() { @Override public Directive apply(Throwable t) { if (t instanceof ArithmeticException) return resume(); else if (t instanceof NullPointerException) return restart(); else return escalate(); } }); ! @Override public SupervisorStrategy supervisorStrategy() { Supervision in Akka Every single actor has a default supervisor strategy. Which is usually sufficient. But it can be overridden.

Slide 88

Slide 88 text

class Supervisor extends UntypedActor { private SupervisorStrategy strategy = new OneForOneStrategy( 10, Duration.parse("1 minute"), new Function() { @Override public Directive apply(Throwable t) { if (t instanceof ArithmeticException) return resume(); else if (t instanceof NullPointerException) return restart(); else return escalate(); } }); ! @Override public SupervisorStrategy supervisorStrategy() { return strategy; } ActorRef worker = context.actorOf(new Props(Worker.class)); public void onReceive(Object message) throws Exception { if (message instanceof Integer) worker.forward(message); } } Supervision in Akka

Slide 89

Slide 89 text

Responsive “Quick to respond or react appropriately” - Merriam Webster

Slide 90

Slide 90 text

Keep latency consistent 1. Blue sky scenarios 2. Traffic bursts 3. Failures

Slide 91

Slide 91 text

Keep latency consistent 1. Blue sky scenarios 2. Traffic bursts 3. Failures The system should always be responsive

Slide 92

Slide 92 text

Use Back Pressure Bounded queues with backoff strategies

Slide 93

Slide 93 text

Use Back Pressure Bounded queues with backoff strategies Respect Little’s Law: L = λW Queue Length = Arrival Rate * Response Time

Slide 94

Slide 94 text

Use Back Pressure Bounded queues with backoff strategies Respect Little’s Law: L = λW Queue Length = Arrival Rate * Response Time Response Time = Queue Length / Arrival Rate

Slide 95

Slide 95 text

Use Back Pressure Bounded queues with backoff strategies Respect Little’s Law: L = λW Queue Length = Arrival Rate * Response Time Response Time = Queue Length / Arrival Rate

Slide 96

Slide 96 text

Use Back Pressure Bounded queues with backoff strategies Respect Little’s Law: L = λW Queue Length = Arrival Rate * Response Time Apply backpressure here Response Time = Queue Length / Arrival Rate

Slide 97

Slide 97 text

Smart Batching Smart Batching http://bit.ly/smartbatching By Martin Thompson

Slide 98

Slide 98 text

Smart Batching Smart Batching http://bit.ly/smartbatching By Martin Thompson

Slide 99

Slide 99 text

Reactive Web & Mobile Apps

Slide 100

Slide 100 text

Reactive Web & Mobile Apps 1. Reactive Request Async & Non-blocking Request & Response

Slide 101

Slide 101 text

Reactive Web & Mobile Apps 1. Reactive Request Async & Non-blocking Request & Response 2. Reactive Composition Reactive Request + Reactive Request + ...

Slide 102

Slide 102 text

Reactive Web & Mobile Apps 1. Reactive Request Async & Non-blocking Request & Response 2. Reactive Composition Reactive Request + Reactive Request + ... 3. Reactive Push Stream Producer

Slide 103

Slide 103 text

Reactive Web & Mobile Apps 1. Reactive Request Async & Non-blocking Request & Response 2. Reactive Composition Reactive Request + Reactive Request + ... 3. Reactive Push Stream Producer 4. 2-way Reactive (Bi-Directional Reactive Push)

Slide 104

Slide 104 text

Reactive Web & Mobile Apps 1. Reactive Request Async & Non-blocking Request & Response 2. Reactive Composition Reactive Request + Reactive Request + ... 3. Reactive Push Stream Producer 4. 2-way Reactive (Bi-Directional Reactive Push)

Slide 105

Slide 105 text

Reactive Web & Mobile Apps 1. Reactive Request Async & Non-blocking Request & Response 2. Reactive Composition Reactive Request + Reactive Request + ... 3. Reactive Push Stream Producer 4. 2-way Reactive (Bi-Directional Reactive Push) Enables Reactive UIs 1. Interactive 2. Data Synchronization 3. “Real-time” Collaboration

Slide 106

Slide 106 text

public class Application extends Controller { public static Result index() { return ok(index.render("Your new application is ready.")); } } Reactive Composition in Play

Slide 107

Slide 107 text

public class Application extends Controller { public static Result index() { return ok(index.render("Your new application is ready.")); } } Reactive Composition in Play standard non-reactive request

Slide 108

Slide 108 text

public class Application extends Controller { public static Result index() { return ok(index.render("Your new application is ready.")); } } Reactive Composition in Play def get(symbol: String): Action[AnyContent] = Action.async { for { tweets <- getTweets(symbol) sentiments <- Future.sequence(loadSentiments(tweets.json)) } yield Ok(toJson(sentiments)) } standard non-reactive request

Slide 109

Slide 109 text

public class Application extends Controller { public static Result index() { return ok(index.render("Your new application is ready.")); } } Reactive Composition in Play def get(symbol: String): Action[AnyContent] = Action.async { for { tweets <- getTweets(symbol) sentiments <- Future.sequence(loadSentiments(tweets.json)) } yield Ok(toJson(sentiments)) } standard non-reactive request fully reactive non-blocking request composition

Slide 110

Slide 110 text

No content

Slide 111

Slide 111 text

http://typesafe.com/platform/getstarted

Slide 112

Slide 112 text

http://typesafe.com/platform/getstarted Demo time

Slide 113

Slide 113 text

Event-Driven Scalable Resilient Responsive

Slide 114

Slide 114 text

Jonas Bonér CTO Typesafe Twitter: @jboner http://reactivemanifesto.org

Slide 115

Slide 115 text

Go Reactive Email: [email protected] Web: typesafe.com Twtr: @jboner