Springone2gx 2014 Reactive Streams and Reactor

75
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission. REACTOR AND THE REACTIVE STREAMS STANDARD Jon Brisbin - Stephane Maldini including plenty of lol™

description

A session about the Reactor story with Reactive Streams pragmatic specification. Talk recorded at SpringOne2GX 2014 Dallas.

Transcript of Springone2gx 2014 Reactive Streams and Reactor

Page 1: Springone2gx 2014 Reactive Streams and Reactor

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

REACTOR AND THE REACTIVE STREAMS STANDARD

Jon Brisbin - Stephane Maldini

including plenty of lol™

Page 2: Springone2gx 2014 Reactive Streams and Reactor

‘Bout the guys speaking

2

!@j_brisbin - 100% asynchronous poet

Reactor Committer I

Reactive-Streams Contributor

!@smaldini - solve 9 issues, create 10 problems

Reactor Committer II

Reactive-Streams Contributor

Page 3: Springone2gx 2014 Reactive Streams and Reactor

Session Manifesto

• Tweet questions during the presentation –@ProjectReactor !

• 90 minutes is long, plenty of time to fall asleep and awake in a storm of nonsense

• Come chat with us after the session

• Jump/Sleep to the last slide to find our coordinates

3

Page 4: Springone2gx 2014 Reactive Streams and Reactor

4

Page 5: Springone2gx 2014 Reactive Streams and Reactor

Aperture Sciences Test 981: Observe the following examples

5

NanoService, MicroService, NotTooBigService™…

Page 6: Springone2gx 2014 Reactive Streams and Reactor

NanoService, MicroService, NotTooBigService™…

6

cat file.csv | sort| grep ‘doge’

Page 7: Springone2gx 2014 Reactive Streams and Reactor

NanoService, MicroService, NotTooBigService™…

7

POST [json] http://dogecoin.money/send/id

—> GET [json] http://dogeprofile.money/id—> POST [json] http://nsa.gov.us/cc/trace/id

Page 8: Springone2gx 2014 Reactive Streams and Reactor

NanoService, MicroService, NotTooBigService™…

8

userService.auth(username,password)—> userService.hashPassword(password)—> userService.findByNameAndHash(name)

Page 9: Springone2gx 2014 Reactive Streams and Reactor

NanoService, MicroService, NotTooBigService™…

9

• A SomethingService will always need to interact • With the user • With other services !

• The boundary between services is the real deal • A big danger lurks in the dark • More breakdown => More boundaries

=> Danger Will Robinson

Page 10: Springone2gx 2014 Reactive Streams and Reactor

10

LatencyAnd this threat has a name

Page 11: Springone2gx 2014 Reactive Streams and Reactor

11

Neither do The Machines

UberFact : Humans don’t really enjoy waiting

Page 12: Springone2gx 2014 Reactive Streams and Reactor

What is latency doing to you ?

12

• Loss of revenues • because users switched to another site/app • because services are compounding inefficiency • because aggressive scaling will be needed • because dev budget will sink into addressing this a postiori

‘2 bucks prediction’ : tech team turnover will increase and keep mourning about how crap is their design

Page 13: Springone2gx 2014 Reactive Streams and Reactor

13

Loading

Page 14: Springone2gx 2014 Reactive Streams and Reactor

All hail Reactive Programming

• A possible answer to this issue

• The very nature of Reactor, look at the name dude

• A fancy buzz-word that might work better than MDA or SOA

• A simple accumulation of years of engineering

14

Page 15: Springone2gx 2014 Reactive Streams and Reactor

No sh*t, what is Reactive Programming ?

15

Low-latency*

Fault-TolerantEvent-Driven

Scalable

Page 16: Springone2gx 2014 Reactive Streams and Reactor

Reactive Architecture ?

• A Reactive system MUST be resilient –splitting concerns to achieve error bulk-heading and

modularity !

• A Reactive system MUST be scalable

– scale-up : partition work across CPUs

– scale-out : distribute over peer nodes

16

Page 17: Springone2gx 2014 Reactive Streams and Reactor

Reactive Architecture !

• Asynchronous Programming is core to Reactive Architecture

• Immediate answer to the originating publisher

• Context segregation to avoid cascade failure as possible

!• Functional Programming fits perfectly as it is stimulus based

• Related: Functional Reactive Programming

17

Page 18: Springone2gx 2014 Reactive Streams and Reactor

18

Reactor has 99 problems but Latency isn’t one

Page 19: Springone2gx 2014 Reactive Streams and Reactor

Reactor-Core features

1919

Functional artifacts (SAM components, tuples, timers)

Event Bus [Reactor.class]

[A]synchronous Dispatchers

Streams and Promises

Fast IO [buffer, net,

persistent queues, codec]

Fast Data [allocators, batch-

processors]

Page 20: Springone2gx 2014 Reactive Streams and Reactor

Dispatching model matters

• Context switching hurts performances

• Locking hurts performances

• Message passing hurts performances

• Blocking for a thread hurts performances

• Resources cost

20

Page 21: Springone2gx 2014 Reactive Streams and Reactor

Built-in UberFast™ dispatcher

• LMAX Disruptor deals with message passing issues

• Based on a Ring Buffer structure

• “Mechanical Sympathy” in Disruptor

!• http://lmax-exchange.github.com/disruptor/files/

Disruptor-1.0.pdf

• http://mechanitis.blogspot.co.uk/2011/06/dissecting-disruptor-whats-so-special.html

21

Page 22: Springone2gx 2014 Reactive Streams and Reactor

Message Passing matters

• Pull vs Push patterns – Push:

• Non blocking programming (e.g. lock-free LMAX RingBuffer) • Functional programming • Best for in-process short access !

– Pull: • Queue based decoupling • Best for slow services or blocking connections

22

Page 23: Springone2gx 2014 Reactive Streams and Reactor

Reactor event bus in action In Groovy because Java doesn’t fit into the slide

23

import reactor.core.Environment import reactor.core.spec.Reactors import reactor.event.Event import static reactor.event.selector.Selectors.$ !def env = new Environment() def r = Reactors.reactor(env) !r.on($('welcome')) { name -> println "hello $name" } !r.notify($('welcome'), Event.wrap('Doge'))

Manage dispatchers

Reactor builder

Send an Event to Topic ‘welcome’

Listen for names on Topic ‘welcome’

Page 24: Springone2gx 2014 Reactive Streams and Reactor

Reactor callback hell In Groovy because Java doesn’t fit into the slide

24

r.on($('talk')) { Event<String> speak -> // do stuff with speak def topic = $("bye-$speak.headers.name") r.notify(topic, Event.wrap("$speak.data, much sad")) } !r.on($('welcome')) { name -> r.on($("bye-$name")){ farewell -> println "bye bye ! $farewell... $name" } def event = Event.wrap('so wow') event.headers['name'] = name r.notify($('talk'), event) } !r.notify($('welcome'), Event.wrap('Doge'))

1st level callback

2nd level callback

3rd nested dynamic callback

Page 25: Springone2gx 2014 Reactive Streams and Reactor

25

Stream?

Page 26: Springone2gx 2014 Reactive Streams and Reactor

26

Stream

Page 27: Springone2gx 2014 Reactive Streams and Reactor

27

Stream!

Page 28: Springone2gx 2014 Reactive Streams and Reactor

28

Stream!

Page 29: Springone2gx 2014 Reactive Streams and Reactor

Solving callback hell

29

import reactor.rx.spec.Streams !def stream = Streams.defer() !stream.map{ name -> Tuple.of(name, 'so wow') }.map{ tuple -> Tuple.of(tuple.name, "$tuple.t2, much sad") }.consume{ tuple -> println "bye bye ! $tuple.t2... $tuple.t1" } !stream.broadcastNext('Doge')

Prepare a simple Stream

1st step

2nd step

Terminal callback

Send some data into the stream

Page 30: Springone2gx 2014 Reactive Streams and Reactor

Using a Stream ?

30

Embedded data-processing Event Handling

Metrics, Statistics Micro-Batching

Composition Feedback-Loop

Page 31: Springone2gx 2014 Reactive Streams and Reactor

Defining a Stream

• Represents a sequence of data, possibly unbounded

• Provide for processing API such as filtering and enrichment • Not a Collection, not a Storage

31

Page 32: Springone2gx 2014 Reactive Streams and Reactor

Stream VS Event Bus [Reactor]

32

• Works great combined (stream distribution)

• Type-checked flow

• Publisher/Subscriber tight control

• No Signal concurrency

Rule of thumb: if nested event composition > 2, switch to Stream

Page 33: Springone2gx 2014 Reactive Streams and Reactor

Hot Stream vs Cold Stream

• An Hot Stream multi-casts real-time signals – think Trade, Tick, Mouse Click !

• A Cold Stream uni-casts deferred signals – think File, Array, Random

33

Page 34: Springone2gx 2014 Reactive Streams and Reactor

34

Introducing Reactive Streams Specification !

Page 35: Springone2gx 2014 Reactive Streams and Reactor

What is defined by Reactive Streams ?

35

Async non-blocking flow-control

Interoperable protocol (Threads, Nodes…)Async non-blocking data sequence

Minimal resources requirement

Page 36: Springone2gx 2014 Reactive Streams and Reactor

Reactive-Streams: Dynamic Message-Passing

36

PUBLISHER

SUBSCRIBER

Events

Demand

Page 37: Springone2gx 2014 Reactive Streams and Reactor

Now You Know

• It is not only queue-based pattern:

– Signaling demand on a slower Publisher == no buffering

– Signaling demand on a faster Publisher == buffering

!• Data volume is bounded by a Subscriber

– Scaling dynamically if required

37

Page 38: Springone2gx 2014 Reactive Streams and Reactor

Out Of The Box : Flow Control

38

PUBLISHER

SUBSCRIBERSlow

SUBSCRIBER

Fast

Page 39: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: Batch Processing ?

• Requesting sized demand allows for batch publishing optimizations

– Could be adapted dynamically based on criteria such as network bandwidth…

– A Publisher could decide to apply grouped operations (aggregating, batch serializing)

39

Page 40: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: What is in the data sequence ?

• If the Publisher is an Hot Stream – Sequence will be defined by when the Subscriber is connected !

• If the Publisher is a Cold Stream – Sequence will be similar for every Subscriber regardless of when

they connected

40

Page 41: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: Transformations ?

• Does not specify any transformation, only essentials components to enable this protocol…

!• …But define a staging component Processor :

– Both A Subscriber AND a Publisher

41

Page 42: Springone2gx 2014 Reactive Streams and Reactor

42

Hold on a minute buddy, there are already Streams in Java 8 !

Page 43: Springone2gx 2014 Reactive Streams and Reactor

All the “Streaming” tech around… Java 8

• Java 8 introduces java.util.stream.Stream – Functional DSL to support transformations and stages – Proactive fetching – No dynamic message passing – Fits nicely with event-driven libraries such as Reactor and RxJava.

43

Page 44: Springone2gx 2014 Reactive Streams and Reactor

All the “Streaming” tech around… Java 8

44

Stream<Widget> widgetsStream = widgets.stream(); ! int sum = widgetsStream .filter(b -> b.getColor() == RED) .mapToInt(b -> b.getWeight()) .sum();

Pull operation

Push operations

Collection to Stream (Cold)

Page 45: Springone2gx 2014 Reactive Streams and Reactor

45

What about RxJava mate ! All those hipsters use it.

Page 46: Springone2gx 2014 Reactive Streams and Reactor

All the “Streaming” tech around… RxJava

• RxJava provides the now famous Reactive Extensions – Rich transformations – Event-Driven (onNext, onError, onComplete) – Flexible scheduling – No dynamic demand OoB(possibly unbounded in-flight data)

46

Page 47: Springone2gx 2014 Reactive Streams and Reactor

All the “Streaming” tech around… Java 8

47

numbers = Observable.from([1, 2, 3, 4, 5]); !numbers.map({it * it}).subscribe( { println(it); }, // onNext { println("Error: " + it.getMessage()); }, // onError { println("Sequence complete"); } // onCompleted );

Push operations

Observe a Cold Stream

Demand ‘all’ data

Page 48: Springone2gx 2014 Reactive Streams and Reactor

Other “Streaming” tech around…

• Streaming data is all the rage in modern frameworks: – Akka, Storm, Reactor, Ratpack, … !

• Semantics compare with Enterprise Integration Patterns: – Camel, Spring Integration/XD, … – However it would technically take multiple channels to model a

single Reactive Streams component (filter, transformer…)

48

Page 49: Springone2gx 2014 Reactive Streams and Reactor

49

ccv

Doug Lea – SUNY Oswego

Reactive Streams: Joining forces

Page 50: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: Joining forces

50

Reactor Data Driver

Akka Distributed

System

RxJava Metrics Pipeline

Ratpack HTTP server

Page 51: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: Joining forces

!• Smart solution and pattern to all reactive applications !

• Writing a standard protocol works best when it is used (!)

!• Beyond the JVM, initial discussions for network stack started

51

Page 52: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: Joining forces

• Semantics – Single document listing full rules – Open enough to allow for various patterns

!• 4 API Interfaces

– Publisher, Subscriber, Subscription, Processor !

• TCK to verify implementation behavior

52

Page 53: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: org.reactivestreams

53

public interface Publisher<T> { public void subscribe(Subscriber<T> s); } !public interface Subscriber<T> { public void onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete(); } !public interface Subscription { public void request(int n); public void cancel(); }

public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {}

Page 54: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: Reactor mapping

54

Publisher

reactor.rx.Stream

Subscriberreactor.rx.actions.Action

Processor

reactor.rx.Promise

Page 55: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: Execution Model

• Publisher creates a capacity-aware container

– Subscription per Subscriber

!• No concurrent notifications on a same Subscriber

!• Asynchronous or Synchronous

– must not impact negatively calling code

55

Page 56: Springone2gx 2014 Reactive Streams and Reactor

Reactive Streams: Signals

56

onError | (onSubscribe onNext* (onError | onComplete)?)

Page 57: Springone2gx 2014 Reactive Streams and Reactor

Resource #1 Resource #4R2 R3

Reactive Streams: Async Boundaries

57

!nioSelectorThreadOrigin map(f) filter(p) consume(toNioSelectorOutput)

Page 58: Springone2gx 2014 Reactive Streams and Reactor

Resource #1 Resource #4

Reactive Streams: Async Boundaries

58

!nioSelectorThreadOrigin map(f) filter(p) consume(toNioSelectorOutput)

Page 59: Springone2gx 2014 Reactive Streams and Reactor

Resource #1 Resource #2

Reactive Streams: Async Boundaries

59

!nioSelectorThreadOrigin map(f) filter(p) consume(toNioSelectorOutput)

Page 60: Springone2gx 2014 Reactive Streams and Reactor

10 slides and a demo to go :):):)

60

Page 61: Springone2gx 2014 Reactive Streams and Reactor

Reactor : Iterable Cold Stream

61

Streams .defer(env, 1, 2, 3, 4, 5) .subscribe(identityProcessor);

Page 62: Springone2gx 2014 Reactive Streams and Reactor

Reactor : Building blackbox processors

62

Processor<Integer,Integer> identityProcessor = Action.<Integer>passthrough(env.getDispatcher("ringBuffer")) .env(env) .capacity(bufferSize) .map(integer -> integer) .distinctUntilChanged() .flatMap(integer -> Promises.success(integer)) .filter(integer -> integer >= 0) .timeout(100) .combine();

Page 63: Springone2gx 2014 Reactive Streams and Reactor

A Full Slide Just To Talk About flatMap()

63

FlatMap Bucket Challenge ! Nominate 3 friends to explain flatMap()

Page 64: Springone2gx 2014 Reactive Streams and Reactor

Another Slide Just To Talk About flatMap()

64

flatMap() is nothing more than the functional alternative to RPC. Just a way to say “Ok bind this incoming data to this sub-flow and listen

for the result, dude”.

Page 65: Springone2gx 2014 Reactive Streams and Reactor

The Last Slide about flatMap()

65

stream.flatMap{ name -> Streams.defer(name) .observe{ println 'so wow' } .map{ 'much monad'} }.consume{ assert it == 'much monad' }

Feed a dynamic Sub-Stream with a name

Sub-Stream definition

Sub-Stream result is merged back to the top-level Steam

Page 66: Springone2gx 2014 Reactive Streams and Reactor

Reactor does also Scale-Up

66

deferred = Streams.defer(environment); deferred .parallel(8) .map(stream -> stream .map(i -> i) .reduce(2, service::reducePairAsMap) .consume(service::forwardToOutput) );

Page 67: Springone2gx 2014 Reactive Streams and Reactor

67

DEMOhttps://github.com/SpringOne2GX-2014/reactive-geocoder

Page 68: Springone2gx 2014 Reactive Streams and Reactor

Early adopters

• Checkpoint –Reactor 2.0.0.BUILD-SNAPSHOT implements 0.4.0.M2 - TCK OK –Akka Streams implements 0.4.0.M2 - TCK OK –Experiments started by RxJava –Ratpack 0.9.9.SNAPSHOT implements 0.4.0.M2 - TCK WIP !

• Links –https://github.com/Netflix/RxJava –http://typesafe.com/blog/typesafe-announces-akka-streams –https://github.com/reactor/reactor –http://www.ratpack.io/manual/0.9.9/streams.html

68

Page 69: Springone2gx 2014 Reactive Streams and Reactor

ReactiveStreams.onSubscribe(Resources)

• www.reactive-streams.org • https://github.com/reactive-streams/reactive-streams !

• on maven central : 0.4.0.M2 – org.reactivestreams/reactive-streams !

• Current TCK preview on repo.akka.io : 0.4.0.M2-SNAPSHOT – org.reactivestreams/reactive-streams-tck

69

Page 70: Springone2gx 2014 Reactive Streams and Reactor

ReactiveStreams.onNext(Roadmap)

• Discussed for inclusion in JDK

• Close to release: 0.4.0 – Evaluating TCK before going 0.4 final

– TCK coverage by Akka Streams and Reactor – Need 3 passing implementations before going 1.0.0.M1

70

Page 71: Springone2gx 2014 Reactive Streams and Reactor

Reactor.onSubscribe(Resources)

• http://projectreactor.cfapps.io/ • https://github.com/reactor • Twitter: @projectReactor !

• on maven central : 2.0.0.BUILD-SNAPSHOT – org.projectreactor/reactor

71

Page 72: Springone2gx 2014 Reactive Streams and Reactor

Reactor.onNext(Roadmap)

• Versions

• Imminent 2.0.0.M1

• 2.0.0.M2 - September

• 2.0.0.RELEASE - End September/Early October • WIP: additional Stream operations, ecosystem upgrade,

new starting guides

72

Page 73: Springone2gx 2014 Reactive Streams and Reactor

Reactor.onError(issues)

• Tracker:

• https://github.com/reactor/reactor/issues

!• Group:

• https://groups.google.com/forum/?#!forum/reactor-framework

73

Page 74: Springone2gx 2014 Reactive Streams and Reactor

74

Q & A

Page 75: Springone2gx 2014 Reactive Streams and Reactor

session.onComplete()

75