148
‹#› © Copyright 2013 Pivotal. All rights reserved. ‹#› © Copyright 2013 Pivotal. All rights reserved. Reactor, Reactive Streams and the MicroService architecture Stephane Maldini

Reactor, Reactive streams and MicroServices

Embed Size (px)

DESCRIPTION

A 1h intro to Reactive Streams relationship with Reactor and how it fits into MicroService

Citation preview

Page 1: Reactor, Reactive streams and MicroServices

‹#›© Copyright 2013 Pivotal. All rights reserved. ‹#›© Copyright 2013 Pivotal. All rights reserved.

Reactor, Reactive Streams andthe MicroService architecture

Stephane Maldini

Page 2: Reactor, Reactive streams and MicroServices

‹#›

@smaldini - solve 9 issues, create 10 problems Customer Success Organization @ Pivotal

Reactor Committer II Try to contribute to Reactive-Streams

Page 3: Reactor, Reactive streams and MicroServices

‹#›

Page 4: Reactor, Reactive streams and MicroServices

‹#›

Aperture Sciences Test 981: Observe the following examples

NanoService, MicroService, NotTooBigService™…

Page 5: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

cat file.csv

Page 6: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

cat file.csv | grep ‘doge’

Page 7: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

cat file.csv | sort| grep ‘doge’

Page 8: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

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

Page 9: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

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

—> GET [json] http://dogeprofile.money/id

Page 10: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

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

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

Page 11: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

userService.auth(username,password)

Page 12: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

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

Page 13: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…

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

Page 14: Reactor, Reactive streams and MicroServices

‹#›

NanoService, MicroService, NotTooBigService™…• A SomethingService will always need to interact

• With the user • With other services

• The boundary between services is the real deal

Page 15: Reactor, Reactive streams and MicroServices

‹#›

And this threat has a name

Page 16: Reactor, Reactive streams and MicroServices

‹#›

LatencyAnd this threat has a name

Page 17: Reactor, Reactive streams and MicroServices

‹#›

UberFact : Humans don’t really enjoy waiting

Page 18: Reactor, Reactive streams and MicroServices

‹#›

Neither do The Machines

UberFact : Humans don’t really enjoy waiting

Page 19: Reactor, Reactive streams and MicroServices

‹#›

What is latency doing to you ?• Loss of revenues

• because users switched to another site/app • because services are compounding inefficiency • because aggressive scaling will be needed

Page 20: Reactor, Reactive streams and MicroServices

‹#›

What is latency doing to you ?• Loss of revenues

• because users switched to another site/app • because services are compounding inefficiency • because aggressive scaling will be needed

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

Page 21: Reactor, Reactive streams and MicroServices

‹#›

Loading

Page 22: Reactor, Reactive streams and MicroServices

‹#›

Loading

Page 23: Reactor, Reactive streams and MicroServices

‹#›

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

Page 24: Reactor, Reactive streams and MicroServices

‹#›

No sh*t, what is Reactive Programming ?

Page 25: Reactor, Reactive streams and MicroServices

‹#›

No sh*t, what is Reactive Programming ?

Event-Driven

Page 26: Reactor, Reactive streams and MicroServices

‹#›

No sh*t, what is Reactive Programming ?

Fault-TolerantEvent-Driven

Page 27: Reactor, Reactive streams and MicroServices

‹#›

No sh*t, what is Reactive Programming ?

Fault-TolerantEvent-Driven

Scalable

Page 28: Reactor, Reactive streams and MicroServices

‹#›

No sh*t, what is Reactive Programming ?

Low-latency*

Fault-TolerantEvent-Driven

Scalable

Page 29: Reactor, Reactive streams and MicroServices

‹#›

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

Page 30: Reactor, Reactive streams and MicroServices

‹#›

Reactor has 99 problems but Latency isn’t one

Page 31: Reactor, Reactive streams and MicroServices

‹#›

Reactor-Core features

17

Page 32: Reactor, Reactive streams and MicroServices

‹#›

Reactor-Core features

17

[A]synchronous Dispatchers

Page 33: Reactor, Reactive streams and MicroServices

‹#›

Reactor-Core features

17

Event Bus [Reactor.class]

[A]synchronous Dispatchers

Page 34: Reactor, Reactive streams and MicroServices

‹#›

Reactor-Core features

17

Event Bus [Reactor.class]

[A]synchronous Dispatchers

Streams and Promises

Page 35: Reactor, Reactive streams and MicroServices

‹#›

Reactor-Core features

17

Functional artifacts (SAM components, tuples, timers)

Event Bus [Reactor.class]

[A]synchronous Dispatchers

Streams and Promises

Page 36: Reactor, Reactive streams and MicroServices

‹#›

Reactor-Core features

17

Functional artifacts (SAM components, tuples, timers)

Event Bus [Reactor.class]

[A]synchronous Dispatchers

Streams and Promises

Fast IO [buffer, net,

persistent queues, codec]

Page 37: Reactor, Reactive streams and MicroServices

‹#›

Reactor-Core features

17

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 38: Reactor, Reactive streams and MicroServices

‹#›

Stream?

Page 39: Reactor, Reactive streams and MicroServices

‹#›

Stream

Page 40: Reactor, Reactive streams and MicroServices

‹#›

Stream!

Page 41: Reactor, Reactive streams and MicroServices

‹#›

Stream!

Page 42: Reactor, Reactive streams and MicroServices

‹#›

import reactor.rx.spec.Streams

def stream = Streams.defer()

stream.map{ name -> Tuple.of(name, 'so wow') }.map{ tuple -> Tuple.of(tuple.t1, "$tuple.t2, much sad") }.consume{ tuple -> println "bye bye ! $tuple.t2... $tuple.t1" }

stream.broadcastNext('Doge')

Using a Stream ?

Page 43: Reactor, Reactive streams and MicroServices

‹#›

import reactor.rx.spec.Streams

def stream = Streams.defer()

stream.map{ name -> Tuple.of(name, 'so wow') }.map{ tuple -> Tuple.of(tuple.t1, "$tuple.t2, much sad") }.consume{ tuple -> println "bye bye ! $tuple.t2... $tuple.t1" }

stream.broadcastNext('Doge')

Prepare a simple Stream

Using a Stream ?

Page 44: Reactor, Reactive streams and MicroServices

‹#›

import reactor.rx.spec.Streams

def stream = Streams.defer()

stream.map{ name -> Tuple.of(name, 'so wow') }.map{ tuple -> Tuple.of(tuple.t1, "$tuple.t2, much sad") }.consume{ tuple -> println "bye bye ! $tuple.t2... $tuple.t1" }

stream.broadcastNext('Doge')

Prepare a simple Stream

1st step

Using a Stream ?

Page 45: Reactor, Reactive streams and MicroServices

‹#›

import reactor.rx.spec.Streams

def stream = Streams.defer()

stream.map{ name -> Tuple.of(name, 'so wow') }.map{ tuple -> Tuple.of(tuple.t1, "$tuple.t2, much sad") }.consume{ tuple -> println "bye bye ! $tuple.t2... $tuple.t1" }

stream.broadcastNext('Doge')

Prepare a simple Stream

1st step

2nd step

Using a Stream ?

Page 46: Reactor, Reactive streams and MicroServices

‹#›

import reactor.rx.spec.Streams

def stream = Streams.defer()

stream.map{ name -> Tuple.of(name, 'so wow') }.map{ tuple -> Tuple.of(tuple.t1, "$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

Using a Stream ?

Page 47: Reactor, Reactive streams and MicroServices

‹#›

import reactor.rx.spec.Streams

def stream = Streams.defer()

stream.map{ name -> Tuple.of(name, 'so wow') }.map{ tuple -> Tuple.of(tuple.t1, "$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

Using a Stream ?

Page 48: Reactor, Reactive streams and MicroServices

‹#›

Using a Stream ?

Embedded data-processing Event Processing

Metrics, Statistics Micro-Batching

Composition Error Handling

Page 49: Reactor, Reactive streams and MicroServices

‹#›

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

Page 50: Reactor, Reactive streams and MicroServices

‹#›

Stream VS Event Bus [Reactor]• Works great combined (stream distribution)

• Type-checked flow

• Publisher/Subscriber tight control

• No Signal concurrency

Page 51: Reactor, Reactive streams and MicroServices

‹#›

Stream VS Event Bus [Reactor]

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

• Works great combined (stream distribution)

• Type-checked flow

• Publisher/Subscriber tight control

• No Signal concurrency

Page 52: Reactor, Reactive streams and MicroServices

‹#›

Hot Stream vs Cold Stream• An Hot Stream multi-casts real-time signals

– think Trade, Tick, Mouse Click, Websocket

• A Cold Stream uni-casts deferred signals – think File, Array, Computation result (Future)

Page 53: Reactor, Reactive streams and MicroServices

‹#›

Reactor : Iterable Cold Stream

Streams .just(1, 2, 3, 4, 5)

.take(3) .subscribe(System.out::println);

Page 54: Reactor, Reactive streams and MicroServices

‹#›

Reactor : AMQP Hot Stream

LapinStreams .fromQueue(queueName) .dispatchOn(Environment.get())

.timeout(30) .subscribe(System.out::println);

Page 55: Reactor, Reactive streams and MicroServices

‹#›

Reactor : AMQP Hot Stream

LapinStreams .fromQueue(queueName) .dispatchOn(Environment.get())

.timeout(30) .subscribe(System.out::println);

COMING SOON IN A REPOSITORY NEAR YOU

Page 56: Reactor, Reactive streams and MicroServices

‹#›

Introducing Reactive Streams Specification !

Page 57: Reactor, Reactive streams and MicroServices

‹#›

What is defined by Reactive Streams ?

Page 58: Reactor, Reactive streams and MicroServices

‹#›

What is defined by Reactive Streams ?

Async non-blocking data sequence

Page 59: Reactor, Reactive streams and MicroServices

‹#›

What is defined by Reactive Streams ?

Async non-blocking data sequence

Minimal resources requirement

Page 60: Reactor, Reactive streams and MicroServices

‹#›

What is defined by Reactive Streams ?

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

Minimal resources requirement

Page 61: Reactor, Reactive streams and MicroServices

‹#›

What is defined by Reactive Streams ?

Async non-blocking flow-control

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

Minimal resources requirement

Page 62: Reactor, Reactive streams and MicroServices

‹#›

Reactive-Streams: Dynamic Message-Passing

Page 63: Reactor, Reactive streams and MicroServices

‹#›

Reactive-Streams: Dynamic Message-Passing

PUBLISHER

Page 64: Reactor, Reactive streams and MicroServices

‹#›

Reactive-Streams: Dynamic Message-Passing

PUBLISHER

SUBSCRIBER

Page 65: Reactor, Reactive streams and MicroServices

‹#›

Reactive-Streams: Dynamic Message-Passing

PUBLISHER

SUBSCRIBER

Page 66: Reactor, Reactive streams and MicroServices

‹#›

Reactive-Streams: Dynamic Message-Passing

PUBLISHER

SUBSCRIBER

Events

Page 67: Reactor, Reactive streams and MicroServices

‹#›

Reactive-Streams: Dynamic Message-Passing

PUBLISHER

SUBSCRIBER

Events

Demand

Page 68: Reactor, Reactive streams and MicroServices

‹#›

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

Page 69: Reactor, Reactive streams and MicroServices

‹#›

Out Of The Box : Flow Control

Page 70: Reactor, Reactive streams and MicroServices

‹#›

Out Of The Box : Flow Control

PUBLISHER

Page 71: Reactor, Reactive streams and MicroServices

‹#›

Out Of The Box : Flow Control

PUBLISHER

SUBSCRIBER

Page 72: Reactor, Reactive streams and MicroServices

‹#›

Out Of The Box : Flow Control

PUBLISHER

SUBSCRIBER

Page 73: Reactor, Reactive streams and MicroServices

‹#›

Out Of The Box : Flow Control

PUBLISHER

SUBSCRIBERSlow

SUBSCRIBER

Page 74: Reactor, Reactive streams and MicroServices

‹#›

Out Of The Box : Flow Control

PUBLISHER

SUBSCRIBERSlow

SUBSCRIBER

Page 75: Reactor, Reactive streams and MicroServices

‹#›

Out Of The Box : Flow Control

PUBLISHER

SUBSCRIBERSlow

SUBSCRIBER

Page 76: Reactor, Reactive streams and MicroServices

‹#›

Out Of The Box : Flow Control

PUBLISHER

SUBSCRIBERSlow

SUBSCRIBER

Fast

Page 77: Reactor, Reactive streams and MicroServices

‹#›

Reactive Streams: Signals

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

Page 78: Reactor, Reactive streams and MicroServices

‹#›

ccv

Doug Lea – SUNY Oswego

Reactive Streams: Joining forces

Page 79: Reactor, Reactive streams and MicroServices

‹#›

Reactor Data Driver

Akka Distributed

System

RxJava Metrics Pipeline

Ratpack HTTP server

Reactive Streams: Joining forces

Page 80: Reactor, Reactive streams and MicroServices

‹#›

Reactor Data Driver

Akka Distributed

System

RxJava Metrics Pipeline

Ratpack HTTP server

Reactive Streams: Joining forces

Page 81: Reactor, Reactive streams and MicroServices

‹#›

Reactor Data Driver

Akka Distributed

System

RxJava Metrics Pipeline

Ratpack HTTP server

Reactive Streams: Joining forces

Page 82: Reactor, Reactive streams and MicroServices

‹#›

Reactor Data Driver

Akka Distributed

System

RxJava Metrics Pipeline

Ratpack HTTP server

Reactive Streams: Joining forces

Page 83: Reactor, Reactive streams and MicroServices

‹#›

Reactor Data Driver

Akka Distributed

System

RxJava Metrics Pipeline

Ratpack HTTP server

Reactive Streams: Joining forces

Page 84: Reactor, Reactive streams and MicroServices

‹#›

Reactor Data Driver

Akka Distributed

System

RxJava Metrics Pipeline

Ratpack HTTP server

Reactive Streams: Joining forces

Page 85: Reactor, Reactive streams and MicroServices

‹#›

Reactor Data Driver

Akka Distributed

System

RxJava Metrics Pipeline

Ratpack HTTP server

Reactive Streams: Joining forces

Page 86: Reactor, Reactive streams and MicroServices

‹#›

Reactive Streams: An industrial matured spec• 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

Page 87: Reactor, Reactive streams and MicroServices

‹#›

Reactive Streams: org.reactivestreamspublic 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(); }

Page 88: Reactor, Reactive streams and MicroServices

‹#›

Reactive Streams: org.reactivestreamspublic 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 89: Reactor, Reactive streams and MicroServices

‹#›

Reactor <=> Reactive Streams

Publisher

reactor.rx.Stream

Subscriberreactor.rx.actions.Action

Processor

reactor.rx.Promise

Page 90: Reactor, Reactive streams and MicroServices

‹#›

Reactor <=> Reactive Streams

Publisher

reactor.rx.Stream

Subscriberreactor.rx.actions.Action

Processor

reactor.rx.Promise

Page 91: Reactor, Reactive streams and MicroServices

‹#›

Reactor <=> Reactive Streams

Publisher

reactor.rx.Stream

Subscriberreactor.rx.actions.Action

Processor

reactor.rx.Promise

Page 92: Reactor, Reactive streams and MicroServices

‹#›

Reactor <=> Reactive Streams

Publisher

reactor.rx.Stream

Subscriberreactor.rx.actions.Action

Processor

reactor.rx.Promise

Page 93: Reactor, Reactive streams and MicroServices

‹#›

Reactor <=> Reactive Streams

Publisher

reactor.rx.Stream

Subscriberreactor.rx.actions.Action

Processor

reactor.rx.Promise

Page 94: Reactor, Reactive streams and MicroServices

‹#›

Reactor <=> Reactive Streams

Publisher

reactor.rx.Stream

Subscriberreactor.rx.actions.Action

Processor

reactor.rx.Promise

Page 95: Reactor, Reactive streams and MicroServices

‹#›

Page 96: Reactor, Reactive streams and MicroServices

‹#›

What about RxJava mate ! All those hipsters use it.

Page 97: Reactor, Reactive streams and MicroServices

‹#›

Reactor == RxJava• Reactor Streams 2.0 are inspired by Rx and RxJava

• http://msdn.microsoft.com/en-gb/data/gg577609.aspx

• Naming and behavior is mostly aligned with RxJava (just, flatMap, retry…)

• Rx Patterns should apply to Reactor Streams

• Lightweight, embeddable

Page 98: Reactor, Reactive streams and MicroServices

‹#›

Reactor != RxJava• Reactor Streams mission:

• Data throughput over Functional facilities (Dispatchers, Subscription model, pre-allocation)

• Pivotal integration (Spring.io, RabbitMQ, Redis, CloudFoundry, Gemfire…)

• Native Reactive Streams, all Stream actions benefit from back pressure model and can talk to any implementation

Page 99: Reactor, Reactive streams and MicroServices

‹#›

slidesSubscription.request(18);

//talkSubscription.cancel();

Page 100: Reactor, Reactive streams and MicroServices

‹#›

Page 101: Reactor, Reactive streams and MicroServices

‹#›

Let’s finish with practical patterns to empoweryour Reactive Service

Page 102: Reactor, Reactive streams and MicroServices

‹#›

Resource #1 Resource #4R2 R3

dispatchOn(dispatcher4)

Reactive Streams: Async Boundaries

httpRequestStream map(f) filter(p) consume(httpResponseConsumer)

dispatchOn(dispatcher1) disp[..] disp[..]

Page 103: Reactor, Reactive streams and MicroServices

‹#›

Resource #1 Resource #4R2 R3

dispatchOn(dispatcher4)

Reactive Streams: Async Boundaries

httpRequestStream map(f) filter(p) consume(httpResponseConsumer)

Not that efficient

dispatchOn(dispatcher1) disp[..] disp[..]

Page 104: Reactor, Reactive streams and MicroServices

‹#›

Resource #1 Resource #4

dispatchOn(dispatcher14)

Reactive Streams: Async Boundaries

httpRequestStream map(f) filter(p) consume(httpResponseConsumer)

dispatchOn(dispatcher1)

Page 105: Reactor, Reactive streams and MicroServices

‹#›

Resource #1 Resource #4

dispatchOn(dispatcher14)

Reactive Streams: Async Boundaries

httpRequestStream map(f) filter(p) consume(httpResponseConsumer)

Non Blocking Stream until last callback

dispatchOn(dispatcher1)

Page 106: Reactor, Reactive streams and MicroServices

‹#›

Resource #1 Resource #2

Reactive Streams: Async Boundaries

httpRequestStream map(f) filter(p) consume(httpResponseConsumer)

dispatchOn(dispatcher1) dispatchOn(dispatcher2)

Page 107: Reactor, Reactive streams and MicroServices

‹#›

Resource #1 Resource #2

Reactive Streams: Async Boundaries

httpRequestStream map(f) filter(p) consume(httpResponseConsumer)

81,2% OK, producer not blocked

dispatchOn(dispatcher1) dispatchOn(dispatcher2)

Page 108: Reactor, Reactive streams and MicroServices

‹#›

A full slide just to say something about FlatMap

Page 109: Reactor, Reactive streams and MicroServices

‹#›

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

A full slide just to say something about FlatMap

Page 110: Reactor, Reactive streams and MicroServices

‹#›

Another one, FlatMap is that cool

Page 111: Reactor, Reactive streams and MicroServices

‹#›

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

for the result, dude”.

Another one, FlatMap is that cool

Page 112: Reactor, Reactive streams and MicroServices

‹#›

Another one, FlatMap is that cool

Page 113: Reactor, Reactive streams and MicroServices

‹#›

Usually in Functional ReactiveProgramming, flatMap is often used for

crossing an async boundary.

Another one, FlatMap is that cool

Page 114: Reactor, Reactive streams and MicroServices

‹#›

Another one, FlatMap is that cool

Page 115: Reactor, Reactive streams and MicroServices

‹#›

This applies to Reactor too, but ALLReactor actions also have built-in

backpressure support and dispatchingfacilities

Another one, FlatMap is that cool

Page 116: Reactor, Reactive streams and MicroServices

‹#›

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

Before you miss it, a FlatMap example

Page 117: Reactor, Reactive streams and MicroServices

‹#›

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

Feed a dynamic Sub-Stream with a name

Before you miss it, a FlatMap example

Page 118: Reactor, Reactive streams and MicroServices

‹#›

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

Feed a dynamic Sub-Stream with a name

Sub-Stream definition

Before you miss it, a FlatMap example

Page 119: Reactor, Reactive streams and MicroServices

‹#›

Streams.just('doge’).flatMap{ name -> Streams.just(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

Before you miss it, a FlatMap example

Page 120: Reactor, Reactive streams and MicroServices

‹#›

deferred = Streams.<String>defer(Environment.get()); deferred .parallel(8) .map(stream -> stream .map(i -> i) .reduce(2, service::reducePairAsMap) .consume(service::forwardToOutput) ).drain();

Doing IO work (esp. O) : Cloning Pipeline

Page 121: Reactor, Reactive streams and MicroServices

‹#›

deferred = Streams.<String>defer(Environment.get()); deferred .parallel(8) .map(stream -> stream .map(i -> i) .reduce(2, service::reducePairAsMap) .consume(service::forwardToOutput) ).drain();

Doing IO work (esp. O) : Cloning PipelineWill create 8 clones competing for upstream data

Page 122: Reactor, Reactive streams and MicroServices

‹#›

deferred = Streams.<String>defer(Environment.get()); deferred .parallel(8) .map(stream -> stream .map(i -> i) .reduce(2, service::reducePairAsMap) .consume(service::forwardToOutput) ).drain();

Doing IO work (esp. O) : Cloning PipelineWill create 8 clones competing for upstream data

Start consuming the full Stream until complete

Page 123: Reactor, Reactive streams and MicroServices

‹#›

Streams.range(1, Integer.MAX_VALUE) .dispatchOn(Environment.masterDispatcher()) .sample(2l, TimeUnit.SECONDS) .dispatchOn(Environment.cachedDispatcher()) .consume{ println it }

Dealing with a nervous Publisher

Page 124: Reactor, Reactive streams and MicroServices

‹#›

Streams.range(1, Integer.MAX_VALUE) .dispatchOn(Environment.masterDispatcher()) .sample(2l, TimeUnit.SECONDS) .dispatchOn(Environment.cachedDispatcher()) .consume{ println it }

Dealing with a nervous Publisher

An intense publisher

Page 125: Reactor, Reactive streams and MicroServices

‹#›

Streams.range(1, Integer.MAX_VALUE) .dispatchOn(Environment.masterDispatcher()) .sample(2l, TimeUnit.SECONDS) .dispatchOn(Environment.cachedDispatcher()) .consume{ println it }

Dealing with a nervous Publisher

An intense publisherAssigned with a global dispatcher

Page 126: Reactor, Reactive streams and MicroServices

‹#›

Streams.range(1, Integer.MAX_VALUE) .dispatchOn(Environment.masterDispatcher()) .sample(2l, TimeUnit.SECONDS) .dispatchOn(Environment.cachedDispatcher()) .consume{ println it }

Dealing with a nervous Publisher

An intense publisherAssigned with a global dispatcher

Retaining a single value every 2s

Page 127: Reactor, Reactive streams and MicroServices

‹#›

Streams.range(1, Integer.MAX_VALUE) .dispatchOn(Environment.masterDispatcher()) .sample(2l, TimeUnit.SECONDS) .dispatchOn(Environment.cachedDispatcher()) .consume{ println it }

Dealing with a nervous Publisher

An intense publisherAssigned with a global dispatcher

Retaining a single value every 2s

Dispatching the sampleswith a different dispatcher to avoid publisher

contention

Page 128: Reactor, Reactive streams and MicroServices

‹#›

def closeCircuit = stream def openCircuit = fallback ?: Streams.<T>fail(new Exception("service unavailable")) def circuitSwitcher = Streams.switchOnNext()

stream .materialize() .window(maxSignals, maxTime) .flatMap{ s -> s.reduce(["failures":0, "success":0]){ tuple -> if(tuple.t2.isOnNext()) tuple.t1.success++ else if(tuple.t2.isOnError()) tuple.t1.failures++ } } .consume({ streamHealth ->

if(streamHealth.failures/(streamHealth.failures + streamHealth.success) > threshold) { Streams.timer(closeTimeout).consume{ circuitSwitcher.onNext(closeCircuit) } circuitSwitcher.onNext(openCircuit) } else { circuitSwitcher.onNext(closeCircuit)

} }, circuitSwitcher.&onError, circuitSwitcher.&onComplete) //start with close circuit circuitSwitcher.onNext(closeCircuit) circuitSwitcher

Failproof: Implementing a Circuit Breaker

Page 129: Reactor, Reactive streams and MicroServices

‹#›

def closeCircuit = stream def openCircuit = fallback ?: Streams.<T>fail(new Exception("service unavailable")) def circuitSwitcher = Streams.switchOnNext()

stream .materialize() .window(maxSignals, maxTime) .flatMap{ s -> s.reduce(["failures":0, "success":0]){ tuple -> if(tuple.t2.isOnNext()) tuple.t1.success++ else if(tuple.t2.isOnError()) tuple.t1.failures++ } } .consume({ streamHealth ->

if(streamHealth.failures/(streamHealth.failures + streamHealth.success) > threshold) { Streams.timer(closeTimeout).consume{ circuitSwitcher.onNext(closeCircuit) } circuitSwitcher.onNext(openCircuit) } else { circuitSwitcher.onNext(closeCircuit)

} }, circuitSwitcher.&onError, circuitSwitcher.&onComplete) //start with close circuit circuitSwitcher.onNext(closeCircuit) circuitSwitcher

Failproof: Implementing a Circuit Breaker

TL;DR

Page 130: Reactor, Reactive streams and MicroServices

‹#›

def closeCircuit = stream def openCircuit = fallback ?: Streams.<T>fail(new Exception("service unavailable")) def circuitSwitcher = Streams.switchOnNext()

stream .materialize() .window(maxSignals, maxTime) .flatMap{ s -> s.reduce(["failures":0, "success":0]){ tuple -> if(tuple.t2.isOnNext()) tuple.t1.success++ else if(tuple.t2.isOnError()) tuple.t1.failures++ } } .consume({ streamHealth ->

if(streamHealth.failures/(streamHealth.failures + streamHealth.success) > threshold) { Streams.timer(closeTimeout).consume{ circuitSwitcher.onNext(closeCircuit) } circuitSwitcher.onNext(openCircuit) } else { circuitSwitcher.onNext(closeCircuit)

} }, circuitSwitcher.&onError, circuitSwitcher.&onComplete) //start with close circuit circuitSwitcher.onNext(closeCircuit) circuitSwitcher

Failproof: Implementing a Circuit Breaker

TL;DR materialize

Page 131: Reactor, Reactive streams and MicroServices

‹#›

def closeCircuit = stream def openCircuit = fallback ?: Streams.<T>fail(new Exception("service unavailable")) def circuitSwitcher = Streams.switchOnNext()

stream .materialize() .window(maxSignals, maxTime) .flatMap{ s -> s.reduce(["failures":0, "success":0]){ tuple -> if(tuple.t2.isOnNext()) tuple.t1.success++ else if(tuple.t2.isOnError()) tuple.t1.failures++ } } .consume({ streamHealth ->

if(streamHealth.failures/(streamHealth.failures + streamHealth.success) > threshold) { Streams.timer(closeTimeout).consume{ circuitSwitcher.onNext(closeCircuit) } circuitSwitcher.onNext(openCircuit) } else { circuitSwitcher.onNext(closeCircuit)

} }, circuitSwitcher.&onError, circuitSwitcher.&onComplete) //start with close circuit circuitSwitcher.onNext(closeCircuit) circuitSwitcher

Failproof: Implementing a Circuit Breaker

TL;DR materialize

window

Page 132: Reactor, Reactive streams and MicroServices

‹#›

def closeCircuit = stream def openCircuit = fallback ?: Streams.<T>fail(new Exception("service unavailable")) def circuitSwitcher = Streams.switchOnNext()

stream .materialize() .window(maxSignals, maxTime) .flatMap{ s -> s.reduce(["failures":0, "success":0]){ tuple -> if(tuple.t2.isOnNext()) tuple.t1.success++ else if(tuple.t2.isOnError()) tuple.t1.failures++ } } .consume({ streamHealth ->

if(streamHealth.failures/(streamHealth.failures + streamHealth.success) > threshold) { Streams.timer(closeTimeout).consume{ circuitSwitcher.onNext(closeCircuit) } circuitSwitcher.onNext(openCircuit) } else { circuitSwitcher.onNext(closeCircuit)

} }, circuitSwitcher.&onError, circuitSwitcher.&onComplete) //start with close circuit circuitSwitcher.onNext(closeCircuit) circuitSwitcher

Failproof: Implementing a Circuit Breaker

TL;DR materialize

window

flatMap

Page 133: Reactor, Reactive streams and MicroServices

‹#›

def closeCircuit = stream def openCircuit = fallback ?: Streams.<T>fail(new Exception("service unavailable")) def circuitSwitcher = Streams.switchOnNext()

stream .materialize() .window(maxSignals, maxTime) .flatMap{ s -> s.reduce(["failures":0, "success":0]){ tuple -> if(tuple.t2.isOnNext()) tuple.t1.success++ else if(tuple.t2.isOnError()) tuple.t1.failures++ } } .consume({ streamHealth ->

if(streamHealth.failures/(streamHealth.failures + streamHealth.success) > threshold) { Streams.timer(closeTimeout).consume{ circuitSwitcher.onNext(closeCircuit) } circuitSwitcher.onNext(openCircuit) } else { circuitSwitcher.onNext(closeCircuit)

} }, circuitSwitcher.&onError, circuitSwitcher.&onComplete) //start with close circuit circuitSwitcher.onNext(closeCircuit) circuitSwitcher

Failproof: Implementing a Circuit Breaker

TL;DR materialize

window

flatMapreduce

Page 134: Reactor, Reactive streams and MicroServices

‹#›

def closeCircuit = stream def openCircuit = fallback ?: Streams.<T>fail(new Exception("service unavailable")) def circuitSwitcher = Streams.switchOnNext()

stream .materialize() .window(maxSignals, maxTime) .flatMap{ s -> s.reduce(["failures":0, "success":0]){ tuple -> if(tuple.t2.isOnNext()) tuple.t1.success++ else if(tuple.t2.isOnError()) tuple.t1.failures++ } } .consume({ streamHealth ->

if(streamHealth.failures/(streamHealth.failures + streamHealth.success) > threshold) { Streams.timer(closeTimeout).consume{ circuitSwitcher.onNext(closeCircuit) } circuitSwitcher.onNext(openCircuit) } else { circuitSwitcher.onNext(closeCircuit)

} }, circuitSwitcher.&onError, circuitSwitcher.&onComplete) //start with close circuit circuitSwitcher.onNext(closeCircuit) circuitSwitcher

Failproof: Implementing a Circuit Breaker

TL;DR materialize

window

flatMapreduce

switchOnNext

Page 135: Reactor, Reactive streams and MicroServices

‹#›

def closeCircuit = stream def openCircuit = fallback ?: Streams.<T>fail(new Exception("service unavailable")) def circuitSwitcher = Streams.switchOnNext()

stream .materialize() .window(maxSignals, maxTime) .flatMap{ s -> s.reduce(["failures":0, "success":0]){ tuple -> if(tuple.t2.isOnNext()) tuple.t1.success++ else if(tuple.t2.isOnError()) tuple.t1.failures++ } } .consume({ streamHealth ->

if(streamHealth.failures/(streamHealth.failures + streamHealth.success) > threshold) { Streams.timer(closeTimeout).consume{ circuitSwitcher.onNext(closeCircuit) } circuitSwitcher.onNext(openCircuit) } else { circuitSwitcher.onNext(closeCircuit)

} }, circuitSwitcher.&onError, circuitSwitcher.&onComplete) //start with close circuit circuitSwitcher.onNext(closeCircuit) circuitSwitcher

Failproof: Implementing a Circuit Breaker

TL;DR materialize

window

flatMapreduce

switchOnNext

timer

Page 136: Reactor, Reactive streams and MicroServices

‹#›

def fallback = Streams.<String>fail(new Exception("Fast fail")

//Open the circuit if there were more than 50% errors over 5 elements or within 3 sec. //Will automatically close the circuit again after 2 sec. Streams.circuitBreaker(stream, fallback, 5, 3, 0.5, 2) .retryWhen{ s -> s.zipWith(Streams.range(1,3)){ tuple.t2 }

.flatMap{ Streams.timer(it) } }

.consume ( { println it }, { println it.message }, { println errors } )

Failproof: Implementing a Circuit Breaker

Page 137: Reactor, Reactive streams and MicroServices

‹#›

def fallback = Streams.<String>fail(new Exception("Fast fail")

//Open the circuit if there were more than 50% errors over 5 elements or within 3 sec. //Will automatically close the circuit again after 2 sec. Streams.circuitBreaker(stream, fallback, 5, 3, 0.5, 2) .retryWhen{ s -> s.zipWith(Streams.range(1,3)){ tuple.t2 }

.flatMap{ Streams.timer(it) } }

.consume ( { println it }, { println it.message }, { println errors } )

Failproof: Implementing a Circuit Breaker

Coming soon™ in M2

Page 138: Reactor, Reactive streams and MicroServices

‹#›

DEMO [if time left > 1.mn]

Page 139: Reactor, Reactive streams and MicroServices

‹#›

Featuring….

RabbitMQ

Ratpack

Reactor Stream

Websocket client (RxJS + Angular)

Page 140: Reactor, Reactive streams and MicroServices

‹#›

Featuring….

RabbitMQ

Ratpack

Reactor Stream

Websocket client (RxJS + Angular)

Page 141: Reactor, Reactive streams and MicroServices

‹#›

Featuring….

RabbitMQ

Ratpack

Reactor Stream

Websocket client (RxJS + Angular)

Page 142: Reactor, Reactive streams and MicroServices

‹#›

Featuring….

RabbitMQ

Ratpack

Reactor Stream

Websocket client (RxJS + Angular)

Page 143: Reactor, Reactive streams and MicroServices

‹#›

Early adopters• Checkpoint

–Reactor 2.0.0.M1 implements 0.4.0 - TCK OK –Akka Streams 0.10-M1 implements 0.4.0 - TCK OK –RxJava - ReactiveStreams 0.3.0 implements 0.4.0 - TCK EVALUATED –Ratpack 0.9.9 implements 0.4.0 - TCK OK

• 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

Page 144: Reactor, Reactive streams and MicroServices

‹#›

ReactiveStreams.onSubscribe(Resources)• www.reactive-streams.org • https://github.com/reactive-streams/reactive-streams

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

Page 145: Reactor, Reactive streams and MicroServices

‹#›

ReactiveStreams.onNext(Roadmap)• Discussed for inclusion in JDK

• Close to release: 1.0.0.M1 – Evaluating TCK before going 1.0 final

– Need 3 fully passing implementations before going 1.0.0.M1

Page 146: Reactor, Reactive streams and MicroServices

‹#›

Reactor.onSubscribe(Resources)• http://projectreactor.cfapps.io/ • https://github.com/reactor • Twitter: @projectReactor • Blog Post: https://spring.io/blog/2014/10/21/reactor-2-0-0-m1-

released-with-reactive-streams-integration • on maven central : 2.0.0.M1, 2.0.0.BUILD-SNAPSHOT

– org.projectreactor/reactor

Page 147: Reactor, Reactive streams and MicroServices

‹#›

Q & A

Page 148: Reactor, Reactive streams and MicroServices

‹#›

session.onComplete()