Go Reactive!

67
Go Reactive! An Overview of the Reactive Programming Paradigm

description

This talk will provide a high-level overview of Reactive web application development. Not only will the 'why' be covered, but also the 'how'. We'll explore a few concrete Reactive design patterns using code examples from Scala and Play, along with Play’s excellent Akka interoperability to demonstrate an underlying message-driven architecture. On that note, we'll discuss two distinct flavours of a message-driven architecture: event-driven and actor-based messaging, and how to pick the right one based on the common advantages and pitfalls of each. By the end of this session you should have a broad overview of why and how to build responsive, resilient, and scalable web applications, using an underlying message-driven architecture to ‘Go Reactive’.

Transcript of Go Reactive!

Page 1: Go Reactive!

Go Reactive!An Overview of the Reactive Programming Paradigm

Page 2: Go Reactive!

Why do we need a different approach?

Page 3: Go Reactive!

–Dan Kegel: The C10k Problem, 1999

“It’s time for web servers to handle ten thousand clients simultaneously.”

Page 4: Go Reactive!

4

• The Internet had 280 million users

• No Facebook, no Twitter

• Snapshots of data, limited streaming

• Response times in seconds

• Downtime all the time

Party like it’s 1999

Page 5: Go Reactive!

5

• Single machines, single cores

• Limited networking

• E.g, a mix of broadband, dialup internet, intranets

• Expensive memory, CPU, hard drives

Hardware in 1999

Page 6: Go Reactive!

6

• “Small data” — i.e, megabytes, gigabytes

• The term “Big Data” was first used in the 1999 paper, “Visually exploring gigabyte

data sets in real time”, published in the Communications of the ACM

Hardware in 1999

Page 7: Go Reactive!

– “Visually exploring gigabyte data sets in real time”, ACM, 1999

“Where megabyte data sets were once considered large, we now find data sets from individual simulations in the 300GB range.”

Page 8: Go Reactive!

–Dan Kegel: The C10k Problem, 1999

“In 1999, one of the busiest FTP sites, cdrom.com, handled 10,000 clients simultaneously through a Gigabit Ethernet pipe.”

Page 9: Go Reactive!

15 years later.

Page 10: Go Reactive!

Expectations have changed. Hardware has changed.

Page 11: Go Reactive!

–Scott Andreas, Urban Airship

“If one node can only serve 10,000 clients, the venture is cost-prohibitive from the start – just one million devices would require a fleet of 100

servers.”

Page 12: Go Reactive!

12

• 1999 — Internet, 280 million users

• 2005 — Internet, 1 billion users

•2014 — Internet, 2.95 billion users

The Internet in 2014

Page 13: Go Reactive!

13

• 1999 — MySpace? Friendster? GeoCities? LiveJournal?

• 2014 — Twitter, 270 million users

•2014 — Facebook, 1.1 billion users

Web applications in 2014

Page 14: Go Reactive!

Facebook alone now handles the user-base of four Internets circa 1999.

Page 15: Go Reactive!

Hardware and data in 2014

15

• A single machine ⇨ clusters of machines

• A single core ⇨ multiple cores

• Slow networks ⇨ fast networks

• Small data snapshots ⇨ big data, streams of data

Page 16: Go Reactive!

Realities of modern software development — 2014

16

• Applications are distributed

• Applications are composed

• Users expect responsiveness — “a slow application is a dead application”

• Users expect adaptation — UIs must adapt to multiple screen sizes and input types

Page 17: Go Reactive!

Developers can no longer avoid parallelism and concurrency.

Page 18: Go Reactive!

In 2010, Urban Airship used Java NIO to successfully test 512,000+ concurrent connections on a single 2.5 GB EC2 instance.

Page 19: Go Reactive!

C10k ⇨ C500k

(Not so fast…)

Page 20: Go Reactive!

–Mihai Rotaru, 2013, discussing MigratoryData WebSocket server

“MigratoryData scales up to 12 million concurrent users from a single Dell PowerEdge R610 server while pushing up to 1.015 Gbps live data

(each user receives a 512-byte message every minute).”

Page 21: Go Reactive!

C10k ⇨ C12m

Page 22: Go Reactive!

What are the principles of Reactive application development?

Page 23: Go Reactive!

–Jonas Bonér

“Instead of the latest framework of the day or the latest buzzword, Reactive brings the talk back to core principles; the design, the

architecture, the way we think about building software.”

Page 24: Go Reactive!

Core principles of reactive application development

24

• React to events ⇨ Message-driven ⇨ The foundation

• React to load ⇨ Scalable ⇨ A trait

• React to failure ⇨ Resilient ⇨ A trait

• React to users ⇨ Responsive ⇨ The goal

Page 25: Go Reactive!

Reactive applications

25

Page 26: Go Reactive!

re·spon·sive !

“Reacting quickly and positively.” !

synonyms: quick to react to, reactive to, receptive to, open to suggestions about, amenable to, flexible to, sensitive to, sympathetic to

Page 27: Go Reactive!

Responsive — flexibility

27

Progressive UI enhancement

• Never allow slow external dependencies to degrade the user experience

Blue skies

• Never assume blue skies, assume grey skies

Page 28: Go Reactive!

Responsive — quick to react

28

Four combinations

• Asynchronous and non-blocking

• Asynchronous and blocking

• Synchronous and non-blocking

• Synchronous and blocking

• Spot the problem combination

Page 29: Go Reactive!

Asynchronous vs synchronous processing times

29

Process 1

Process 2

Process 3

0 ms 425 ms

200 ms

75 ms

150 ms

Asynchronous - 200ms

Process 1 Process 2 Process 3

0 ms 425 ms

Synchronous - 425ms

• Staying async — and in the future — ensures that processing time is not bounded by IO

• Async processing is limited by only the longest running process

• Synchronous processing is limited by the combined processing times

• Stay async!

Page 30: Go Reactive!

Responsiveness with

Page 31: Go Reactive!

31

1. mydomain.com/admin/settings

renders views.html.admin HTML

2. Browser fetches static assets served

from outside of Play

3. Ajax requests — Play serves JSON

via a RESTful API

HTML for views.html.admin(...)

Browser Play

CDN

HTTP GET (mydomain.com/admin/settings)

JS, CSS, images, etc

HTTP GET (mydomain.com/ws/some/services)

JSON

Page 32: Go Reactive!

Example template with AngularJS

32

• Scala template rendered by Twirl and returned by Play controller

• HTML inserted into ng-view by Angular controller after initial page render

@(customer: Customer)!!<head>...</head>!<body>! <div class="wrapper">! <header>…</header>! <h1>Welcome @customer.name!</h1>! <section id="body" ng-app="ngAdmin">! <div ng-view></div>! </section>! <footer>...</footer>! </div>!</body>!</html>

HeaderPlay handles navigation

Footer

load async || fail whale

load async || omit

AngularJS

Page 33: Go Reactive!

Responsiveness !

Being quick to react to all users of a system — under blue skies and grey skies — in order to ensure a consistent experience.

Page 34: Go Reactive!

scal·able !

“Capable of being easily expanded or upgraded on demand.” !

synonyms: ascendable, climbable, extensible, expandable, expansible, adaptable, elastic, flexible

Page 35: Go Reactive!

Scalable — terms

35

• Performance is a measurement of response time — the goal

• Load impacts performance if not handled properly — the enemy

Page 36: Go Reactive!

Scalable — how to deal with load?

36

• Scale up — faster CPU, more memory, bigger hard drive

• More efficient use of existing resources

• Scale out — distribute work across workers

• Elasticity, provisioning new resources on demand

• Location transparency

Page 37: Go Reactive!

Scalability with

Page 38: Go Reactive!

38

• Actors can communicate across thread boundaries and across network boundaries

• Pure message passing enables distribution

• Distribution provides concurrency

Actor Mailbox

IsolatedState

Actor Mailbox

IsolatedState

Scalable — Location transparency

Page 39: Go Reactive!

39

class GameActor extends Actor {! def receive = {! case handshakeRequest: HandshakeRequest => ! sender ! computeHandshakeResponse(handshakeRequest)! case turnMessage: TurnMessage => ! sender ! computeTurnResponse(turnMessage) ! }!}!

!

• Time, space, mutation ⇨ flow, events, messages

Scalable — Akka actor example

Page 40: Go Reactive!

Reference Architecture

40

PlayServer

AkkaMasterRouter

AkkaStandbyRouter

AkkaWorker

AkkaWorker

AkkaWorker

AkkaWorker

PlayServer

PlayServer

PlayServer

https://typesafe.com/activator/template/akka-distributed-workers

Page 41: Go Reactive!

Scalable — Akka remoting

41

• Creating a remote actorval ref = system.actorOf(FooActor.props.withDeploy(Deploy(scope = RemoteScope(address))))!

• Referencing a remote actorval remoteFooActor = context.actorSelection("akka.tcp://[email protected]:2552/user/fooActor")

Page 42: Go Reactive!

42

akka {! actor {! provider = "akka.remote.RemoteActorRefProvider"! }! remote {! transport = "akka.remote.netty.NettyRemoteTransport"! netty {! hostname = "127.0.0.1"! port = 2552! }! }!}

Scalable — Akka remoting example config

Page 43: Go Reactive!

Scalability !

The capability of your system to be easily upgraded on demand in order to ensure responsiveness under various load conditions.

Page 44: Go Reactive!

re·sil·ient !

“Able to withstand or recover quickly from difficult conditions.” !

synonyms: strong, tough, hardy

Page 45: Go Reactive!

Resilient

45

Bulkheads • Partitioning — partition thread groups for different functionality

Circuit Breakers • Stability — Failing external dependencies shouldn’t bring down an entire app

Backpressure • Throttling — wait for a consumer to demand more work to avoid fast producers

overwhelming slow consumers

• Example: http://typesafe.com/activator/template/akka-stream-scala

Page 46: Go Reactive!

Resilience with

Page 47: Go Reactive!

Circuit Breaker

47

Closed

OpenHalf-Open

attemptreset

trip reset

Page 48: Go Reactive!

Play — BlockingCircuitBreaker.scala

48

import akka.pattern.CircuitBreaker!import play.api.libs.concurrent.Akka!import play.api.Play.current!import scala.concurrent.duration.DurationInt!!object BlockingCircuitBreaker {! val circuitBreaker = {! val maxFailures = current.configuration.getInt(“properties.cb.maxFailures").getOrElse(1)! val callTimeout = current.configuration.getInt(“properties.cb.callTO").getOrElse(10)! val resetTimeout = current.configuration.getInt(“properties.cb.resetTO").getOrElse(100)! val cb = new CircuitBreaker(! executor = ThreadPools.blockingPool,! scheduler = Akka.system.scheduler,! maxFailures = maxFailures,! callTimeout = callTimeout.milliseconds,! resetTimeout = resetTimeout.milliseconds! )! cb.onOpen(someAlertOperation)! cb! }!}!

Page 49: Go Reactive!

Play — How to handle failure?

49

package object circuitbreaker { ! def catchOpenCircuitBreaker(r: Future[Result]): Future[Result] = { ! r recover { case _: CircuitBreakerOpenException => {! Results.InternalServerError(…)! }! }! }!}!

Page 50: Go Reactive!

Play — Controller-tier

50

import circuitbreakers.BlockingCircuitBreaker.circuitBreaker.withCircuitBreaker!!val futureResult = withCircuitBreaker({…})!!catchOpenCircuitBreaker {! futureResult.map { r =>!! Results.Ok(…)! }!}!

Page 51: Go Reactive!

Why circuit breakers?

51

• Prevent failures from overwhelming strained services and cascading

• Codify strategies to address the inevitable failure of external systems

• Prepare for failure early

• Play + Akka + Circuit breakers provides an extremely resilient web foundation!

Page 52: Go Reactive!

Resiliency !

The proper application of fundamental design and architecture principles to ensure responsiveness under grey skies.

Page 53: Go Reactive!

e·vent !

“Something that happens or is regarded as happening; an occurrence, especially one of some importance.”

!

driv·en !

“Propelled or motivated by something.”

Page 54: Go Reactive!

Traditional concurrency

54

Thread based concurrency with objects and shared state • Imperative, sequential execution

• Threads for concurrency

• Mutable objects, shared state

• Most common paradigm

• Implementations — Java Enterprise Edition, Wicket, etc

Page 55: Go Reactive!

Traditional concurrency

55

Software transactional memory (STM) • Immutable values

• Atomicity, consistency, isolation and durability

• Cannot perform any operation that cannot be undone, including (most) I/O

• Think command pattern/interface

• Implementations — Haskell STM (native), libs for Scala, Java, OCaml, Clojure, etc

Page 56: Go Reactive!

Share nothing concurrency

56

Event-driven concurrency • Thread based event loops

• Typically single threaded

• Implementations — Node.js, Twisted Python, EventMachine (Ruby)

Page 57: Go Reactive!

Share nothing concurrency

57

Actor-based concurrency • Mutable state, but completely isolated (state can only be mutated by the actor)

• Asynchronous message passing between actors using mailboxes

• Implementations — Erlang, Akka

Page 58: Go Reactive!

Events versus messages

58

• Events happen

• Interested observers must watch for and respond to events

• Anonymous function callbacks lead to the deeply nested “pyramid of doom”

• Messages are directed

• Messages can be directed to one receiver or broadcast to a number of receivers

• Directed messages avoid the pyramid of doom

Page 59: Go Reactive!

Message-driven !

A message-driven architecture forces programmers to deal with scalability and resilience at a code level in order to facilitate

responsiveness.

Page 60: Go Reactive!

re·ac·tive !

“Responsive to stimulus.” !

synonyms: active, aware, conscious, receptive, sensitive, acknowledging, alive, answering

Page 61: Go Reactive!

Reactive

61

Page 62: Go Reactive!

Erlang has embraced the tenets of reactive programming since 1985.

Page 63: Go Reactive!

Erlang characteristics and use cases

63

• Share nothing architecture — processes cannot share data

• Pure message passing — copy all the data you need in the messages

• Crash detection and recovery — things will crash, so let them crash then recover

Page 64: Go Reactive!

Erlang characteristics and use cases

64

Popular Erlang Software • Wings 3D — 3D modelling • Ejabberd — instant messaging server • CouchDB — document database • RabbitMQ — enterprise-y messaging

Erlang in Production • Ericsson — 3G mobile networks

• Amazon — SimpleDB, EC2

• Facebook — back-end chat server

• T-Mobile — SMS and authentication

Page 65: Go Reactive!

–Jonas Bonér

“Reactive looks back in history. It doesn't ignore the goldmine of knowledge that's been around for 30 to 40 years, but rather tries to bring

it into new context.”

Page 66: Go Reactive!

Sources and credits

66

• Jonas Bonér — Reactive Supply to Changing Demand

• Joe Armstrong — K things I know about building Resilient Reactive Systems

• Benjamin Erb — Concurrent Programming for Scalable Web Architectures

• Rich Hickey — The Value of Values

• Plus various talks, papers, books, blog posts, and tweets by Dean Wampler, Erik Meijer, Martin Odersky, Martin Thompson, and many more

Page 67: Go Reactive!

©Typesafe 2014 – All Rights Reserved