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

The Reactive Revolution

The Reactive Revolution

The Reactive Revolution - Introduction to Reactive Programming & Project Reactor

Avatar for Shai Gabai

Shai Gabai

March 01, 2018
Tweet

More Decks by Shai Gabai

Other Decks in Programming

Transcript

  1. The Reactive Revolution • Reactive System • Reactive Streams •

    Reactive Programming • Reactive Manifesto • Reactive Spring • RX Java • Project Reactor • Vert.x • Akka • Responsive • Resilient • Elastic • Message Driven • Asynchronous • Back Pressure • Non Blocking • Callback Hell • Scalable
  2. • Why going reactive? • What does Reactive mean? •

    Reactive Streams • Project Reactor • Building Reactive Application • Q&A Agenda
  3. Async and Blocking • Huge numbers of concurrent users •

    Application performance improvements • Parallelization approach: • Use more threads and hardware resources
  4. Blocking can be Wasteful • Blocking wastes resources • DB

    requests • Network call • Threads sits idle and waiting for data • Memory consumption Memory Number of Treads
  5. Asynchronous • Java offers two models of asynchronous programming •

    Callbacks • Callbacks are hard to compose together - known as "Callback Hell" • Futures • Easy to block – get • Complex orchestrating beyond one level of composition • No support for multiple values and advanced error handling
  6. Asynchronous – Callback Hell userService.getFavorites(userId, new Callback<List<String>>() { public void

    onSuccess(List<String> list) { if (list.isEmpty()) { suggestionService.getSuggestions(new Callback<List<Favorite>>() { public void onSuccess(List<Favorite> list) { UiUtils.submitOnUiThread(() -> { list.stream().limit(5).forEach(uiList::show); }); } public void onError(Throwable error) { UiUtils.errorPopup(error); } }); } else { list.stream().limit(5).forEach(favId -> favoriteService.getDetails(favId, new Callback<Favorite>() { public void onSuccess(Favorite details) { UiUtils.submitOnUiThread(() -> uiList.show(details)); } public void onError(Throwable error) { UiUtils.errorPopup(error); } } )); } } public void onError(Throwable error) { UiUtils.errorPopup(error); } });
  7. The Reactive Manifesto • Responsive • a reactive system needs

    to handle requests in a reasonable time. • Resilient • a reactive system must stay responsive in the face of failures. • it must be designed for failures and deal with them appropriately. • Elastic • a reactive system must stay responsive under various loads. • it must scale up/down and be able to handle the load with minimal resources. • Message Driven • components from a reactive system interacts using asynchronous message passing.
  8. Reactive Programming • Event driven • Failures as messages •

    Backpressure • Non blocking • Asynchronous
  9. Event Loop Single Thread Event Event Event Event Queue Event

    Handlers Handler Handler Handler Request Operation
  10. Event Loop Single Thread Event Event Event Request Event Queue

    Event Handlers Handler Handler Handler Operation Blocking Operation
  11. Event Loop Single Thread Event Event Event Event Queue Event

    Handlers Operation Completed Handler Handler Handler Request Operation Blocking Operation
  12. Reactive Programming • Declarative • Readable • Maintainable • Testable

    userService.getFavorites(userId) .flatMap(favoriteService::getDetails) .switchIfEmpty(suggestionService.getSuggestions()) .take(5) .publishOn(UiUtils.uiThreadScheduler()) .subscribe(uiList::show, UiUtils::errorPopup);
  13. Reactive Streams • Contract between implementors • Non blocking •

    Asynchronous • Backpressure • Data flow • Specification - API • TCK – Technology Compatibility Kit • http://www.reactive-streams.org/
  14. Reactive Streams • API Components (interfaces): • Publisher • Subscriber

    • Subscription • Processor • https://github.com/reactive-streams/reactive-streams-jvm
  15. Reactive Streams • Subscriber public interface Subscriber<T> { public void

    onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete(); }
  16. Reactive Streams – Data Flow Publisher • subscribe Subscriber •

    onSubscribe • onNext • onError • onComplete Subscription • request(n) • cancel
  17. • Subscriber request canceled • Publisher completed the process •

    Error occurred Reactive Streams – Data Flow
  18. Publisher Operator Operator Operator Subscriber subscribe Data Flow – Chain

    Declaration Nothing Happens Until You subscribe()
  19. Publisher Subscriber Data Flow – Chain Declaration onNext onComplete onError

    Operator Sub Pub Operator Sub Pub Operator Sub Pub
  20. Reactive Streams – Java 9 Flow • Flow.Publisher<T> • subscribe

    • Flow.Subscriber<T> • onSubscribe • onNext • onError • onComplete • Flow.Sucscription • request n • cancel • Flow.Processor<T,R> extends Flow.Subscriber<T>, Flow.Publisher<R>
  21. Reactive Streams – Java Implementations • RxJava • David Karnok

    – a key committer • Reactor • David Karnok – a committer • Akka Streams • Ratpack • Vert.x
  22. Project Reactor • The default reactive programming library of Spring

    5 • Based on java 8 (CompletableFuture, Streams, Duration) • Two publishers: • Flux<T> • Mono<T> • Reactive Streams all the way
  23. Project Reactor – Flux • Asynchronous Sequence of 0-N Items

    • Collection or infinite items • A Flux<T> is a standard Publisher<T> • Calls to a downstream object’s onNext, onComplete or onError
  24. Project Reactor – Mono • Asynchronous 0-1 Result • Void

    or Single Object • A Mono<T> is a specialized Publisher<T> • Terminates with an onComplete or onError
  25. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow
  26. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow 2
  27. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow 3 6
  28. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow 4 9 6
  29. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow 12 6 onComplete
  30. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow 12 onComplete
  31. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow onComplete 12
  32. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow onComplete
  33. Flux.range (2, 3) map (i -> i * 3) distinct()

    filter (i -> i % 2 == 0) Subscriber Project Reactor – Data Flow
  34. Project Reactor – Data Flow Flux.range(2, 3) .map(i -> i

    * 3) .filter(i -> i % 2 == 0) .distinct() .subscribe() 2, 3, 4 | 6, 9, 12 | 6, 12 | 6, 12 |
  35. Project Reactor – flatMap Flux.range(2, 3) .flatMap(i -> Flux.range(i*10, 2))

    .subscribe() 2, 3, 4 | 20, 21 | 30, 31 | 40, 41 | 20, 21, 30, 31, 40, 41 |
  36. Project Reactor – concat Flux f1 = Flux.range(1, 3) Flux

    f2 = Flux.range(4, 3) Flux.concat(f1, f2) .subscribe() 1, 2, 3 | 4, 5, 6 | 1, 2, 3, 4, 5, 6 |
  37. Project Reactor – merge Flux f1 = Flux.range(1, 3) Flux

    f2 = Flux.range(4, 3) Flux.merge(f1, f2) .subscribe() 1, 2, 3 | 4, 5, 6 | 1, 4, 5, 2, 3, 6 |
  38. Project Reactor – zip Flux f1 = Flux.range(1, 3) Flux

    f2 = Flux.range(4, 3) Flux.zip(f1, f2) .subscribe() 1, 2, 3 | 4, 5, 6 | [1,4],[2,5],[3,6] |
  39. • Reactor is Concurrency Agnostic • it does not enforce

    a concurrency model • Scheduler – the execution model and where the execution happens • immediate – current thread • single – reuses the same thread for all callers • newSingle – a per-call dedicated thread • elastic – elastic thread pool • creates new worker pools as needed • reuse idle ones • worker pools that stay idle for long time are disposed • parallel – fixed thread pool • creates as many workers as you have CPU cores Schedulers and Threading
  40. • Reactor offers two means of switching the execution context:

    subscribeOn and publishOn operators • subscribeOn • applies to the subscription process, when that backward chain is constructed. • it always affects the context of the source emission. • publishOn • applies in the same way as any other operator, in the middle of the subscriber chain. • it affects where the subsequent operators will execute Schedulers and Threading
  41. Building Reactive Application • Reactive all the way • WebFlux

    • Reactive Messages • Reactive Repository
  42. The Reactive Rush • Reactive all the way • Web

    layer • Server layers • Database • MongoDB • Cassandra • Redis • Couchbase
  43. Blocking Repository List<User> findAll(); • Method returns when whole list

    is received void save(User user); • Throws exception if an error happens
  44. Mono<User> findOne(String id); • Mono<User> means error or success "onComplete"

    event. • One element received Flux<User> findAll(); • Method returns immediately • Elements are received as soon as they are available, ending with a success "onComplete" event. Reactive Repository
  45. Summary • Modern software • Blocking is evil • What

    does Reactive mean • Reactive Manifesto • Reactive Streams • Project Reactor • Building Reactive Application • Reactive all the way