Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactor - A foundation for asynchronous applications on the JVM

Reactor - A foundation for asynchronous applications on the JVM

The sheer volume of non-human-generated data in modern applications can easily overtake a traditional single-threaded, blocking design model. Reactor aims to address this volume, by providing a foundational framework for JVM applications -- applications that need high throughput when performing reasonably small chunks of stateless, asynchronous processing. Join Jon Brisbin as he discusses the motivations behind the project, the design patterns and existing technology that inspired the project, and how it fits in the asynchronous ecosystem today, as a teaser to his upcoming session at SpringOne 2GX 2013.

Jon Brisbin

June 18, 2013
Tweet

More Decks by Jon Brisbin

Other Decks in Programming

Transcript

  1. 1 1 A foundation for asynchronous applications on the JVM

    Jon Brisbin Senior Software Engineer, Pivotal Reactor Project Lead @j_brisbin github.com/jbrisbin
  2. 2 2 Reactor - Intro  JVM applications have limited

    async, fast-data options. • Most solutions are limited in scope. • Usually address only a specific concern (async/fast or data).  Async, fast-data applications need all the throughput possible. • Usually willing to trade off some bells and whistles in the library.  Lots of event-driven development in the last 20 years. Make use of it. • None of us are operating in a vacuum.
  3. 3 3 Reactor - modules FactoryBean @On spring TcpServer TcpClient

    Codec tcp core Fn Reactor Stream Promise DSL Closures groovy
  4. 4 4 Reactor isn't...  ...traditional, idiomatic Java. • $(“topic”);

    U(“/bucket/{key}”); R(“topic.([0-9]+)”); • ObjectSelector.objectSelector(“topic”); • UriTemplateSelector.uriTemplateSelector(“/bucket/{key}”); • RegexSelector.regexSelector(“topic.([0-9]+)”); • Reactor r = R.reactor().using(env).get();  ...a runtime • But you could build one with Reactor. • Tries not to make assumptions about where Reactor apps run. • Provides building blocks, not finished solutions.  ...Akka • Clustering components will come to Reactors in future. • Reactors aren't Actors. • Reactor aims to be very, very lightweight, minimal deps.
  5. 5 5 Reactor – Use Cases  High-speed ingestion. •

    Reactor TcpServer provides millions of events/sec depending on machine capabilities (RAM, IO speed, etc...).  High-throughput event processing. • Loosely-connect components via Events.  Asynchronous processing. • Servlet 3.1 • Java Main • Batch/Integration
  6. 6 6 Reactor – Performance  Various Dispatchers based on

    need. • eventLoop – BlockingQueue • threadPool – Thread Pool Executor • ringBuffer – Disruptor RingBuffer  >10,000,000 events/second on a dual-core i7 MacBook Pro. • RingBuffer  >20,000,000 events/second on a quad-core i7 (8 virtual procs). • RingBuffer
  7. 9 9 Reactor – API Environment env = new Environment();

    Reactor reactor = R.reactor() .using(env) // long-lived env .dispatcher(Environment.RING_BUFFER) // Disruptor .get(); // Supplier.get() reactor.on( $("trade.execute"), // like a topic (Event<Trade> ev) -> { // lambda as callback server.execute(tradeEvent.getData()); } ); (Java 8 with lambdas)
  8. 10 10 Reactor – API def reactor = R.reactor() .using(env)

    .dispatcher(Environment.RING_BUFFER) .get() reactor.on($("trade.execute")) { Trade trade -> server.execute trade } (Groovy with Closures)
  9. 11 11 Reactor – API – Consumers Selector topic =

    $("mytopic"); reactor.on(topic, new Consumer<Event<String>>() { public void accept(String s) { // handle String value } }); Event<String> ev = Event.wrap("Hello World!"); reactor.notify("mytopic", ev);  Traditional callback-style abstraction.  Identical to JDK 8 java.util.function.Consumer.  Meant to be replaced by standard JDK 8 in future.
  10. 12 12 Reactor – API – Selectors Selector topic =

    $("mytopic"); reactor.on(topic, ev -> service::handleEvent); reactor.notify("mytopic", topicEvent); Like a topic in messaging systems.
  11. 13 13 Reactor – API – Selectors final Object key

    = new Object(); Selector sel = ObjectSelector.objectSelector(key); reactor.on(sel, new Consumer<Event<Pojo>>() { public void accept(Event<Pojo> ev) { // handle Event } }); reactor.notify(key, objEvent); ...can also be objects...
  12. 14 14 Reactor – API – Selectors def uri =

    Fn.U("/bucket/{key}") reactor.on(uri) { KvEvent kvEvent -> // handle event def key = kvEvent.headers.get(“key”) } reactor.notify "/bucket/mykeyvalue", kvEvent ...can also be URI templates...
  13. 15 15 Reactor – API – Composable – Stream Stream<String>

    stream = S.<String>defer() .using(env) .dispatcher(Environment.RING_BUFFER) .get(); stream.accept("string1"); ... stream.accept("string999");  Magic Bus love child of callback and functional approaches.  Inspired by RxJava, Groovy, even Erlang.  Directly transform value using map, filter, reduce.
  14. 16 16 Reactor – API – Composable – Stream stream.consume(new

    Consumer<String>() { public void accept(String s) { // handle String } });  Streams can be consumed...
  15. 17 17 Reactor – API – Composable – Stream Stream<String>

    hello = stream.map( new Function<String, String>() { public String apply(String name) { // return something different return "Hello " + name + "!"; } } );  Streams can be transformed...
  16. 18 18 Reactor – API – Composable – Stream Stream

    stream = Streams.each([1, 2, 3, 4, 5]) .sync() .get() Stream avg = stream.reduce { i, avg=0 -> (i + avg) / 2 }  Streams can be reduced...
  17. 19 19 Reactor – API – Composable – Promise Promise<String>

    p = P.<String>defer() .sync() .get(); p.then( s -> { /* handle String */ }, t -> { /* handle Throwable */ } );  Based on Promises/A+ spec. http://promises-aplus.github.io/promises-spec/  Single-use Composable.  Can still use map, filter, etc...
  18. 20 20 Reactor – API – Composable – Promise promise.onComplete(new

    Consumer<Promise<String>>() { public void accept(Promise<String> p) { // handle Promise when success OR failure } });  Promises can be Consumed...
  19. 21 21 Reactor – API – Composable – Promise def

    promise = Promises.success('Hello World'). sync(). get() promise.onSuccess({ s -> // handle String } as Consumer<String>) promise.onError({ x -> // handle Exception } as Consumer<Throwable>)  Promises invoke Consumers if fulfilled...
  20. 22 22 Reactor – API – Composable – Promise Promise<Pojo>

    pojoPromise = stringPromise.map( new Function<String, Pojo>() { public Pojo apply(String s) { return new Pojo(s); } } ); Pojo pojo = pojoPromise.get();  Promises can be mapped...
  21. 24 24 Reactor – Resources  https://github.com/reactor/reactor  reactor-framework Google

    Group  @ProjectReactor on Twitter  https://speakerdeck.com/jbrisbin  https://springone2gx.com/conference/santa_clara/2013/09/register  http://en.wikipedia.org/wiki/Reactor_pattern  https://github.com/LMAX-Exchange/disruptor  https://github.com/netflix/rxjava