designing for distributed systems with reactor and reactive streams

101
Designing for Distributed Systems with Reactor and Reactive Streams Stephane Maldini @smaldini 1

Upload: stephane-maldini

Post on 03-Aug-2015

918 views

Category:

Software


2 download

TRANSCRIPT

Page 1: Designing for Distributed Systems with Reactor and Reactive Streams

Designing  for  Distributed  Systems  with  Reactor  and  Reactive  Streams

Stephane  Maldini  @smaldini

1

Page 2: Designing for Distributed Systems with Reactor and Reactive Streams

WHY  DISTRIBUTED  SYSTEMS  ARE  THE  NEW  NORMAL  ?

Page 3: Designing for Distributed Systems with Reactor and Reactive Streams

SCALING  MONOLITHIC  APPS

Payments Adult

E-­‐Learning Entertainment

Music Search

Payments Adult

E-­‐Learning Entertainment

Music Search

Payments Adult

E-­‐Learning Entertainment

Music Search

Payments Adult

E-­‐Learning Entertainment

Music Search

Page 4: Designing for Distributed Systems with Reactor and Reactive Streams

HOW  YOU  SHOULD  SCALE  ?

Page 5: Designing for Distributed Systems with Reactor and Reactive Streams

HOW  YOU  SHOULD  SCALE  ?

Enternaiment

E-­‐Learning

Payments

Adult

Music

Search

Requests

Page 6: Designing for Distributed Systems with Reactor and Reactive Streams
Page 7: Designing for Distributed Systems with Reactor and Reactive Streams

MICROSERVICES

Page 8: Designing for Distributed Systems with Reactor and Reactive Streams

Dependencies ?

Page 9: Designing for Distributed Systems with Reactor and Reactive Streams

The  Speed  Of  Light

I wish I acted in Star Trek Teleporting anyone ?

Page 10: Designing for Distributed Systems with Reactor and Reactive Streams

There’s  latency  between  each  remote  call

Page 11: Designing for Distributed Systems with Reactor and Reactive Streams

Let’s  use  asynchronous  processing

There’s  latency  between  each  remote  call

Page 12: Designing for Distributed Systems with Reactor and Reactive Streams

Let’s  use  asynchronous  processing

I  shall  not  block  incoming  requests  to  keep  serving

There’s  latency  between  each  remote  call

Page 13: Designing for Distributed Systems with Reactor and Reactive Streams

Let’s  use  asynchronous  processing

I  shall  not  block  incoming  requests  to  keep  serving

Thread  Executor  !

There’s  latency  between  each  remote  call

Page 14: Designing for Distributed Systems with Reactor and Reactive Streams

private ExecutorService threadPool = Executors.newFixedThreadPool(2); final List<T> batches = new ArrayList<T>();

//…

Callable<T> t = new Callable<T>() {

public T run() { T result = callDatabase(); synchronized(batches) { batches.add(result); return result; } } };

Future<T> f = threadPool.submit(t); T result = f.get()

Vanilla  background-­‐processing

Page 15: Designing for Distributed Systems with Reactor and Reactive Streams

private ExecutorService threadPool = Executors.newFixedThreadPool(2); final List<T> batches = new ArrayList<T>();

//…

Callable<T> t = new Callable<T>() {

public T run() { T result = callDatabase(); synchronized(batches) { batches.add(result); return result; } } };

Future<T> f = threadPool.submit(t); T result = f.get()

New  Allocation  By  Request

Vanilla  background-­‐processing

Page 16: Designing for Distributed Systems with Reactor and Reactive Streams

private ExecutorService threadPool = Executors.newFixedThreadPool(2); final List<T> batches = new ArrayList<T>();

//…

Callable<T> t = new Callable<T>() {

public T run() { T result = callDatabase(); synchronized(batches) { batches.add(result); return result; } } };

Future<T> f = threadPool.submit(t); T result = f.get()

New  Allocation  By  Request

Queue-­‐based  message  passing

Vanilla  background-­‐processing

Page 17: Designing for Distributed Systems with Reactor and Reactive Streams

private ExecutorService threadPool = Executors.newFixedThreadPool(2); final List<T> batches = new ArrayList<T>();

//…

Callable<T> t = new Callable<T>() {

public T run() { T result = callDatabase(); synchronized(batches) { batches.add(result); return result; } } };

Future<T> f = threadPool.submit(t); T result = f.get()

New  Allocation  By  Request

Queue-­‐based  message  passing

Vanilla  background-­‐processing

What  if  this  message  fails  ?

Page 18: Designing for Distributed Systems with Reactor and Reactive Streams

private ExecutorService threadPool = Executors.newFixedThreadPool(2); final List<T> batches = new ArrayList<T>();

//…

Callable<T> t = new Callable<T>() {

public T run() { T result = callDatabase(); synchronized(batches) { batches.add(result); return result; } } };

Future<T> f = threadPool.submit(t); T result = f.get()

New  Allocation  By  Request

Queue-­‐based  message  passing

Vanilla  background-­‐processing

What  if  this  message  fails  ?

censored

Page 19: Designing for Distributed Systems with Reactor and Reactive Streams

Mixing  latency  with  queue  based  handoff

http://ferd.ca/queues-don-t-fix-overload.html

Page 20: Designing for Distributed Systems with Reactor and Reactive Streams

Mixing  latency  with  queue  based  handoff

http://ferd.ca/queues-don-t-fix-overload.html

Page 21: Designing for Distributed Systems with Reactor and Reactive Streams

Mixing  latency  with  queue  based  handoff

http://ferd.ca/queues-don-t-fix-overload.html

Page 22: Designing for Distributed Systems with Reactor and Reactive Streams

Queues  must  be  bounded

Page 23: Designing for Distributed Systems with Reactor and Reactive Streams

Passing  message  /w  little  overhead

Queues  must  be  bounded

Page 24: Designing for Distributed Systems with Reactor and Reactive Streams

Passing  message  /w  little  overhead

Tolerating  some  consuming  rate  difference

Queues  must  be  bounded

Page 25: Designing for Distributed Systems with Reactor and Reactive Streams

Passing  message  /w  little  overhead

Tolerating  some  consuming  rate  difference

Reactor  !

Queues  must  be  bounded

Page 26: Designing for Distributed Systems with Reactor and Reactive Streams

Pre-­‐allocating  Slots  -­‐>  The  Ring  Buffer

Publishing events to the right slot

dude!

Page 27: Designing for Distributed Systems with Reactor and Reactive Streams

Re-­‐using  Threads  too  :  Event  Loop

I’m an event loop, consuming messages in the right order

Page 28: Designing for Distributed Systems with Reactor and Reactive Streams

//RingBufferProcessor with 32 slots by default RingBufferProcessor<Integer> processor = RingBufferProcessor.create(); //Subscribe to receive events processor.subscribe( //Create a subscriber from a lambda/method ref SubscriberFactory.unbounded((data, s) ->

System.out.println(data) )

);

//Dispatch data asynchronously int i = 0; while(i++ < 100000) processor.onNext(i)

//Terminate the processor processor.shutdown();

Page 29: Designing for Distributed Systems with Reactor and Reactive Streams

//a second subscriber to receive the same events in a distinct thread processor.subscribe( SubscriberFactory.unbounded((data, s) -> {

//a slow callback returning false when not interested in data anymore if(!sometimeSlow(data)){ //shutdown the consumer thread s.cancel();

}

}) );

Page 30: Designing for Distributed Systems with Reactor and Reactive Streams
Page 31: Designing for Distributed Systems with Reactor and Reactive Streams

Hold  on  !  The  guy  said  bounded  number  of  slots

Page 32: Designing for Distributed Systems with Reactor and Reactive Streams

So  we  still  block  when  the  buffer  is  full!

Hold  on  !  The  guy  said  bounded  number  of  slots

Page 33: Designing for Distributed Systems with Reactor and Reactive Streams

So  we  still  block  when  the  buffer  is  full!

…So  why  sending  more  requests

Hold  on  !  The  guy  said  bounded  number  of  slots

Page 34: Designing for Distributed Systems with Reactor and Reactive Streams

So  we  still  block  when  the  buffer  is  full!

…So  why  sending  more  requests

Reactive  Streams!

Hold  on  !  The  guy  said  bounded  number  of  slots

Page 35: Designing for Distributed Systems with Reactor and Reactive Streams

What  is  defined  in  Reactive  Streams

Page 36: Designing for Distributed Systems with Reactor and Reactive Streams

Async non-blocking data sequence

What  is  defined  in  Reactive  Streams

Page 37: Designing for Distributed Systems with Reactor and Reactive Streams

Async non-blocking data sequence

Minimal resources requirement

What  is  defined  in  Reactive  Streams

Page 38: Designing for Distributed Systems with Reactor and Reactive Streams

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

Minimal resources requirement

What  is  defined  in  Reactive  Streams

Page 39: Designing for Distributed Systems with Reactor and Reactive Streams

Async non-blocking flow-control

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

Minimal resources requirement

What  is  defined  in  Reactive  Streams

Page 40: Designing for Distributed Systems with Reactor and Reactive Streams

Async non-blocking flow-control

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

Minimal resources requirement

What  is  defined  in  Reactive  Streams

Page 41: Designing for Distributed Systems with Reactor and Reactive Streams

What  is  reactive  flow  control  ?

Page 42: Designing for Distributed Systems with Reactor and Reactive Streams

PUBLISHER

What  is  reactive  flow  control  ?

Page 43: Designing for Distributed Systems with Reactor and Reactive Streams

PUBLISHER

SUBSCRIBER

What  is  reactive  flow  control  ?

Page 44: Designing for Distributed Systems with Reactor and Reactive Streams

PUBLISHER

SUBSCRIBER

What  is  reactive  flow  control  ?

SUBSCRIPTION

Page 45: Designing for Distributed Systems with Reactor and Reactive Streams

PUBLISHER

SUBSCRIBER

Events

What  is  reactive  flow  control  ?

SUBSCRIPTION

Page 46: Designing for Distributed Systems with Reactor and Reactive Streams

PUBLISHER

SUBSCRIBER

Events

What  is  reactive  flow  control  ?

SUBSCRIPTION

Page 47: Designing for Distributed Systems with Reactor and Reactive Streams

PUBLISHER

SUBSCRIBER

Events

Demand

What  is  reactive  flow  control  ?

SUBSCRIPTION

Page 48: Designing for Distributed Systems with Reactor and Reactive Streams

All  of  that  in  4  interfaces!

Page 49: Designing for Distributed Systems with Reactor and Reactive Streams

And  there’s  a  TCK  to  verify  implementations

All  of  that  in  4  interfaces!

Page 50: Designing for Distributed Systems with Reactor and Reactive Streams

And  there’s  a  TCK  to  verify  implementations

No  More  Unwanted  Requests

All  of  that  in  4  interfaces!

Page 51: Designing for Distributed Systems with Reactor and Reactive Streams

And  there’s  a  TCK  to  verify  implementations

No  More  Unwanted  Requests

Need  to  propagate  that  demand  upstream!

All  of  that  in  4  interfaces!

Page 52: Designing for Distributed Systems with Reactor and Reactive Streams

ccv

Doug Lea – SUNY Oswego

Some  Smart  Guys  Involved

Page 53: Designing for Distributed Systems with Reactor and Reactive Streams

RingBufferProcessor<Integer> processor = RingBufferProcessor.create(); //Subscribe to receive event […]

//Data access gated by a Publisher with backpressure PublisherFactory.forEach( sub -> { if(sub.context().hasNext()) sub.onNext(sub.context().readInt());

else sub.onComplete();

}, sub -> sqlContext(), context -> context.close()

) .subscribe(processor);

//Terminate the processor [..]

Page 54: Designing for Distributed Systems with Reactor and Reactive Streams

RingBufferProcessor<Integer> processor = RingBufferProcessor.create(); //Subscribe to receive event […]

//Data access gated by a Publisher with backpressure PublisherFactory.forEach( sub -> { if(sub.context().hasNext()) sub.onNext(sub.context().readInt());

else sub.onComplete();

}, sub -> sqlContext(), context -> context.close()

) .subscribe(processor);

//Terminate the processor [..]Connect  processor  to  this  publisher  and  start  requesting

Page 55: Designing for Distributed Systems with Reactor and Reactive Streams

RingBufferProcessor<Integer> processor = RingBufferProcessor.create(); //Subscribe to receive event […]

//Data access gated by a Publisher with backpressure PublisherFactory.forEach( sub -> { if(sub.context().hasNext()) sub.onNext(sub.context().readInt());

else sub.onComplete();

}, sub -> sqlContext(), context -> context.close()

) .subscribe(processor);

//Terminate the processor [..]Connect  processor  to  this  publisher  and  start  requesting

For  the  new  connected  processor,  create  some  sql  

context

Page 56: Designing for Distributed Systems with Reactor and Reactive Streams

RingBufferProcessor<Integer> processor = RingBufferProcessor.create(); //Subscribe to receive event […]

//Data access gated by a Publisher with backpressure PublisherFactory.forEach( sub -> { if(sub.context().hasNext()) sub.onNext(sub.context().readInt());

else sub.onComplete();

}, sub -> sqlContext(), context -> context.close()

) .subscribe(processor);

//Terminate the processor [..]Connect  processor  to  this  publisher  and  start  requesting

For  the  new  connected  processor,  create  some  sql  

context

Keep  invoking  this  callback  until  there  is  no  more  

pending  request

Page 57: Designing for Distributed Systems with Reactor and Reactive Streams

What  about  combining  multiple  asynchronous  calls

Page 58: Designing for Distributed Systems with Reactor and Reactive Streams

And  everything  in  a  controlled  fashion

What  about  combining  multiple  asynchronous  calls

Page 59: Designing for Distributed Systems with Reactor and Reactive Streams

And  everything  in  a  controlled  fashion

Including  Errors  and  Completion  

What  about  combining  multiple  asynchronous  calls

Page 60: Designing for Distributed Systems with Reactor and Reactive Streams

And  everything  in  a  controlled  fashion

Including  Errors  and  Completion  

Reactive  Extensions  !

What  about  combining  multiple  asynchronous  calls

Page 61: Designing for Distributed Systems with Reactor and Reactive Streams

FlatMap  and  Monads..  Nooooo  Please  No

24

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

Page 62: Designing for Distributed Systems with Reactor and Reactive Streams

FlatMap  and  Monads..  Nooooo  Please  No

24

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

A publisher that only sends “doge” on request

Page 63: Designing for Distributed Systems with Reactor and Reactive Streams

FlatMap  and  Monads..  Nooooo  Please  No

24

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

A publisher that only sends “doge” on request

Sub-Stream definition

Page 64: Designing for Distributed Systems with Reactor and Reactive Streams

FlatMap  and  Monads..  Nooooo  Please  No

24

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

A publisher that only sends “doge” on request

Sub-Stream definition

All Sub-Streams are merged under a single sequence

Page 65: Designing for Distributed Systems with Reactor and Reactive Streams

Scatter  Gather  and  Fault  Tolerance

25

Streams.merge(      userService.filteredFind(“Rick"),  //  Stream  of  User      userService.filteredFind(“Morty")  //  Stream  of  User  )  .buffer()  //  Accumulate  all  results  in  a  List  .retryWhen(  errors  -­‐>  //Stream  of  Errors      errors      .zipWith(Streams.range(1,3),  t  -­‐>  t.getT2())          .flatMap(  tries  -­‐>  Streams.timer(tries)  )  )  .consume(System.out::println);

Page 66: Designing for Distributed Systems with Reactor and Reactive Streams

Scatter  Gather  and  Fault  Tolerance

25

Interleaved merge from 2 upstream publishers

Streams.merge(      userService.filteredFind(“Rick"),  //  Stream  of  User      userService.filteredFind(“Morty")  //  Stream  of  User  )  .buffer()  //  Accumulate  all  results  in  a  List  .retryWhen(  errors  -­‐>  //Stream  of  Errors      errors      .zipWith(Streams.range(1,3),  t  -­‐>  t.getT2())          .flatMap(  tries  -­‐>  Streams.timer(tries)  )  )  .consume(System.out::println);

Page 67: Designing for Distributed Systems with Reactor and Reactive Streams

Scatter  Gather  and  Fault  Tolerance

25

Interleaved merge from 2 upstream publishers

Up to 3 tries

Streams.merge(      userService.filteredFind(“Rick"),  //  Stream  of  User      userService.filteredFind(“Morty")  //  Stream  of  User  )  .buffer()  //  Accumulate  all  results  in  a  List  .retryWhen(  errors  -­‐>  //Stream  of  Errors      errors      .zipWith(Streams.range(1,3),  t  -­‐>  t.getT2())          .flatMap(  tries  -­‐>  Streams.timer(tries)  )  )  .consume(System.out::println);

Page 68: Designing for Distributed Systems with Reactor and Reactive Streams

Scatter  Gather  and  Fault  Tolerance

25

Interleaved merge from 2 upstream publishers

Up to 3 tries

All Sub-Streams are merged under a single sequence

Streams.merge(      userService.filteredFind(“Rick"),  //  Stream  of  User      userService.filteredFind(“Morty")  //  Stream  of  User  )  .buffer()  //  Accumulate  all  results  in  a  List  .retryWhen(  errors  -­‐>  //Stream  of  Errors      errors      .zipWith(Streams.range(1,3),  t  -­‐>  t.getT2())          .flatMap(  tries  -­‐>  Streams.timer(tries)  )  )  .consume(System.out::println);

Page 69: Designing for Distributed Systems with Reactor and Reactive Streams

Scatter  Gather  and  Fault  Tolerance

25

Interleaved merge from 2 upstream publishers

Up to 3 tries

All Sub-Streams are merged under a single sequence

Streams.merge(      userService.filteredFind(“Rick"),  //  Stream  of  User      userService.filteredFind(“Morty")  //  Stream  of  User  )  .buffer()  //  Accumulate  all  results  in  a  List  .retryWhen(  errors  -­‐>  //Stream  of  Errors      errors      .zipWith(Streams.range(1,3),  t  -­‐>  t.getT2())          .flatMap(  tries  -­‐>  Streams.timer(tries)  )  )  .consume(System.out::println);

Delay retry

Page 70: Designing for Distributed Systems with Reactor and Reactive Streams

REACTOR2™  =    REACTOR  +  REACTIVE  EXTENSIONS  +  REACTIVE  STREAMS

Page 71: Designing for Distributed Systems with Reactor and Reactive Streams

reactor-net

reactor-streams

reactor-bus

reactor-core

Page 72: Designing for Distributed Systems with Reactor and Reactive Streams

reactor-net

reactor-streams

reactor-bus

reactor-core

Event Bus

Core Dispatchers & Processors

Streams and Promises

Page 73: Designing for Distributed Systems with Reactor and Reactive Streams

reactor-net

reactor-streams

reactor-bus

reactor-coreFunctional artifacts

(SAM components, tuples, timers)

Event Bus

Core Dispatchers & Processors

Streams and Promises

Page 74: Designing for Distributed Systems with Reactor and Reactive Streams

reactor-net

reactor-streams

reactor-bus

reactor-coreFunctional artifacts

(SAM components, tuples, timers)

Event Bus

Core Dispatchers & Processors

Streams and Promises

NetStreams [ Clients/Server ] [TCP, UDP, HTTP]

Page 75: Designing for Distributed Systems with Reactor and Reactive Streams

reactor-net

reactor-streams

reactor-bus

reactor-coreFunctional artifacts

(SAM components, tuples, timers)

Event Bus

Core Dispatchers & Processors

Streams and Promises

NetStreams [ Clients/Server ] [TCP, UDP, HTTP]

Fast Data [buffer, codec]

Page 76: Designing for Distributed Systems with Reactor and Reactive Streams

reactor-net

reactor-streams

reactor-bus

reactor-coreFunctional artifacts

(SAM components, tuples, timers)

Event Bus

Core Dispatchers & Processors

Streams and Promises

NetStreams [ Clients/Server ] [TCP, UDP, HTTP]

Fast Data [buffer, codec]

Page 77: Designing for Distributed Systems with Reactor and Reactive Streams

reactor-net

reactor-streams

reactor-bus

reactor-coreFunctional artifacts

(SAM components, tuples, timers)

Event Bus

Core Dispatchers & Processors

Streams and Promises

NetStreams [ Clients/Server ] [TCP, UDP, HTTP]

Fast Data [buffer, codec]

Page 78: Designing for Distributed Systems with Reactor and Reactive Streams

ASYNC  IO  ?

Page 79: Designing for Distributed Systems with Reactor and Reactive Streams
Page 80: Designing for Distributed Systems with Reactor and Reactive Streams

30

NetStreams.<String,  String>httpServer(spec  -­‐>        spec.codec(StandardCodecs.STRING_CODEC).listen(3000)  ).     ws("/",  channel  -­‐>  {       System.out.println("Connected  a  websocket  client:  "  +  channel.remoteAddress());  

    return  somePublisher.         window(1000).         flatMap(s  -­‐>  channel.writeWith(  s.  

reduce(0f,  (prev,  trade)  -­‐>  (trade.getPrice()  +  prev)  /  2).  map(Object::toString)  )  

);     }).     start().     await();

Page 81: Designing for Distributed Systems with Reactor and Reactive Streams

30

NetStreams.<String,  String>httpServer(spec  -­‐>        spec.codec(StandardCodecs.STRING_CODEC).listen(3000)  ).     ws("/",  channel  -­‐>  {       System.out.println("Connected  a  websocket  client:  "  +  channel.remoteAddress());  

    return  somePublisher.         window(1000).         flatMap(s  -­‐>  channel.writeWith(  s.  

reduce(0f,  (prev,  trade)  -­‐>  (trade.getPrice()  +  prev)  /  2).  map(Object::toString)  )  

);     }).     start().     await();

Listen  on  port  3000  and  convert  bytes  into  String  inbound/

outbound

Page 82: Designing for Distributed Systems with Reactor and Reactive Streams

30

NetStreams.<String,  String>httpServer(spec  -­‐>        spec.codec(StandardCodecs.STRING_CODEC).listen(3000)  ).     ws("/",  channel  -­‐>  {       System.out.println("Connected  a  websocket  client:  "  +  channel.remoteAddress());  

    return  somePublisher.         window(1000).         flatMap(s  -­‐>  channel.writeWith(  s.  

reduce(0f,  (prev,  trade)  -­‐>  (trade.getPrice()  +  prev)  /  2).  map(Object::toString)  )  

);     }).     start().     await();

Listen  on  port  3000  and  convert  bytes  into  String  inbound/

outbound

Upgrade  clients  to  websocket  on  root  URI

Page 83: Designing for Distributed Systems with Reactor and Reactive Streams

30

NetStreams.<String,  String>httpServer(spec  -­‐>        spec.codec(StandardCodecs.STRING_CODEC).listen(3000)  ).     ws("/",  channel  -­‐>  {       System.out.println("Connected  a  websocket  client:  "  +  channel.remoteAddress());  

    return  somePublisher.         window(1000).         flatMap(s  -­‐>  channel.writeWith(  s.  

reduce(0f,  (prev,  trade)  -­‐>  (trade.getPrice()  +  prev)  /  2).  map(Object::toString)  )  

);     }).     start().     await();

Listen  on  port  3000  and  convert  bytes  into  String  inbound/

outbound

Upgrade  clients  to  websocket  on  root  URI

Flush  every  1000  data  some  data  with  writeWith  +  window

Page 84: Designing for Distributed Systems with Reactor and Reactive Streams

30

NetStreams.<String,  String>httpServer(spec  -­‐>        spec.codec(StandardCodecs.STRING_CODEC).listen(3000)  ).     ws("/",  channel  -­‐>  {       System.out.println("Connected  a  websocket  client:  "  +  channel.remoteAddress());  

    return  somePublisher.         window(1000).         flatMap(s  -­‐>  channel.writeWith(  s.  

reduce(0f,  (prev,  trade)  -­‐>  (trade.getPrice()  +  prev)  /  2).  map(Object::toString)  )  

);     }).     start().     await();

Listen  on  port  3000  and  convert  bytes  into  String  inbound/

outbound

Upgrade  clients  to  websocket  on  root  URI

Flush  every  1000  data  some  data  with  writeWith  +  windowClose  connection  when  

flatMap  completes,  which  is  when  all  Windows  are  done

Page 85: Designing for Distributed Systems with Reactor and Reactive Streams

THE  STATE  OF  THE  ART

Page 86: Designing for Distributed Systems with Reactor and Reactive Streams

Nowreactive-­‐streams.1.0.0  

50%  guide  complete  :  http://projectreactor.io/docs/reference    

reactor-­‐*.2.0.3.RELEASE  -­‐  2.0.4  around  the  corner  

reactor-­‐*.2.1.0.BUILD-­‐SNAPSHOT  -­‐  early  access,  no  breaking  changes  

Page 87: Designing for Distributed Systems with Reactor and Reactive Streams

Now

Initial  Reactor  2  Support  in  :  Spring  Integration  4.2  Spring  Messaging  4.2  Spring  Boot  1.3    Spring  XD  1.2  Grails  3.0

Page 88: Designing for Distributed Systems with Reactor and Reactive Streams

After  Now

Spring  Integration  DSL  +  Reactive  Streams  Dynamic  Subscribers  on  Predefined  Channels  !  Best  Tool  for  each  job:  SI  for  integrating  Reactor  for  scaling  up  too  fast  to  be  true

Page 89: Designing for Distributed Systems with Reactor and Reactive Streams

SI  Java  DSL  +  Reactive  Stream  Preview@Configuration @EnableIntegration public static class ContextConfiguration {

@Autowired private TaskScheduler taskScheduler;

@Bean public Publisher<Message<String>> reactiveFlow() { return IntegrationFlows .from(“inputChannel”) .split(String.class, p -> p.split(",")) .toReactiveStreamsPublisher(); }

@Bean public Publisher<Message<Integer>> pollableReactiveFlow() { return IntegrationFlows .from("inputChannel") .split(e -> e.get().getT2().setDelimiters(",")) .<String, Integer>transform(Integer::parseInt) .channel(Channels::queue) .toReactiveStreamsPublisher(this.taskScheduler); }

}

Page 90: Designing for Distributed Systems with Reactor and Reactive Streams

After  Now

Reactor  +  Spring  Cloud  •  Annotation  Driven  FastData  •  Async  IO  :  (proxy,  client)  •  Circuit  breaker,  Bus,  …  

Reactor  +  Spring  XD  •  Scale  up  any  XD  pipeline  •Reactive  Backpressure  in  XD

Page 91: Designing for Distributed Systems with Reactor and Reactive Streams

37

@EnableReactorModule(concurrency  =  5)  public  class  PongMessageProcessor  implements  ReactiveProcessor<Message,  Message>  {         @Override     public  void  accept(Stream<Message>  inputStream,  ReactiveOutput<Message>  output)  {       output.writeOutput(           inputStream               .map(simpleMap())               .observe(simpleMessage())       );     }  

  //…  }  

Page 92: Designing for Distributed Systems with Reactor and Reactive Streams

37

@EnableReactorModule(concurrency  =  5)  public  class  PongMessageProcessor  implements  ReactiveProcessor<Message,  Message>  {         @Override     public  void  accept(Stream<Message>  inputStream,  ReactiveOutput<Message>  output)  {       output.writeOutput(           inputStream               .map(simpleMap())               .observe(simpleMessage())       );     }  

  //…  }  

Split  input  XD  channel  in  5  threads  !  With  a  blazing  fast  Processor

Page 93: Designing for Distributed Systems with Reactor and Reactive Streams

37

@EnableReactorModule(concurrency  =  5)  public  class  PongMessageProcessor  implements  ReactiveProcessor<Message,  Message>  {         @Override     public  void  accept(Stream<Message>  inputStream,  ReactiveOutput<Message>  output)  {       output.writeOutput(           inputStream               .map(simpleMap())               .observe(simpleMessage())       );     }  

  //…  }  

Split  input  XD  channel  in  5  threads  !  With  a  blazing  fast  Processor

Register  the  sequence  to  write  on  the  output  channel  after  some  operations

Page 94: Designing for Distributed Systems with Reactor and Reactive Streams

After

<3  Spring  5  +  Reactor  &  Reactive  Streams  <3

Page 95: Designing for Distributed Systems with Reactor and Reactive Streams

After

Reactive  IPC  for  the  JVM  <3  RxNetty  +  reactor-­‐net  <3  

Reactor  2.0.3.+  already  previews  the  concept  and  API  flavor…  

because  REACTOR  DOESN’T  KNOW  WAITING  (LOL)

Page 96: Designing for Distributed Systems with Reactor and Reactive Streams

Future  ??

• RxJava  2.0  timeline  (2016  and  after?)  • Thanks  Interop,  Reactive  Extensions  and  Naming  conventions,  it  can  converge  with  reactor-­‐streams  

• https://github.com/ReactiveX/RxJava/wiki/Reactive-­‐Streams  

Page 97: Designing for Distributed Systems with Reactor and Reactive Streams

Take-­‐away

• Distributed  System  is  the  new  cool  and  comes  at  some  cost,  two  big  ones  are  Latency  and  Failure  Tolerance  

• Asynchronous  Processing  and  Error  Handling  by  Design  deal  with  these  two  problems  -­‐>  Reactor,  Reactive  Extensions  /  Streams  

• However  to  fully  operate,  Asynchronous  Processing  should  be  bounded  proactively  (stop-­‐read)  -­‐>  Reactive  Streams

Page 98: Designing for Distributed Systems with Reactor and Reactive Streams
Page 99: Designing for Distributed Systems with Reactor and Reactive Streams

REACTIVE

Page 100: Designing for Distributed Systems with Reactor and Reactive Streams

Extra

Page 101: Designing for Distributed Systems with Reactor and Reactive Streams

Take-­‐away  links

• http://reactive-­‐streams.org    • http://projectreactor.io    • https://github.com/spring-­‐projects/spring-­‐integration-­‐java-­‐dsl/pull/31  

• https://github.com/smaldini/spring-­‐xd/tree/refresh-­‐reactor-­‐module/spring-­‐xd-­‐reactor/    

• https://github.com/reactive-­‐ipc/reactive-­‐ipc-­‐jvm    • https://github.com/smaldini/ReactiveStreamsExamples