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

Project Reactor

Kengo TODA
September 19, 2018

Project Reactor

A simple explanation about how we can apply project reactor to app.
It also explains about a required paradigm shift to code.

Kengo TODA

September 19, 2018
Tweet

More Decks by Kengo TODA

Other Decks in Technology

Transcript

  1. PROJECT REACTOR
    2018-09-12 Kengo TODA
    1

    View Slide

  2. OBJECTIVE
    • Understand the best practices for multi-thread app
    • Understand a paradigm shift in daily coding
    • Learn how Spring Framework is going to apply these solutions
    2

    View Slide

  3. WHOAMI
    • Kengo TODA
    • FOSS developer for 17+ years
    • https://github.com/KengoTODA/
    • A core member of SpotBugs
    3

    View Slide

  4. AGENDA
    • Best practice to code multi-thread app, and in reality
    • You are not coding a procedure!
    • Project Reactor the latest approach
    • Can we use Project Reactor in production?
    4

    View Slide

  5. BEST PRACTICE TO CODE
    MULTI-THREAD APP, AND IN REALITY
    5

    View Slide

  6. WHY MULTI-THREAD APP IS NECESSARY
    • Current architecture of computer: bottleneck exists in CPU and I/O
    • One machine has many CPU cores
    • Network is enough fast
    • Compute & store in parallel for better throughput
    6

    View Slide

  7. WHY MULTI-THREAD APP IS DIFFICULT
    • Race condition
    • Hard to reproduce & debug
    • Amdahl’s law
    7

    View Slide

  8. BEST PRACTICES
    • Stateless service, Immutable data (e.g. @Value in lombok, Immutables)
    • Ownership (e.g. Rust)
    • Non-blocking I/O (e.g. Netty)
    • Idempotence, Stateless, Actor model (e.g. Akka), Reentrant, Thread-
    safe, lock-free, CAS, etc.
    8

    View Slide

  9. IN REALITY…
    • We need state!
    • We everyday persist some onto database
    • Cache is necessary but it’s also a kind of state
    • Ownership needs support from system
    9

    View Slide

  10. IN REALITY…
    • Immutable data is hard to handle
    • Do we need Builder & copy constructor everywhere?
    • Java’s clone() is almost broken (see EffectiveJava)
    • Java has no Object.assign() in JavaScript
    • Some framework expects that data is not immutable (!!??)
    10

    View Slide

  11. IN REALITY…
    • Non-blocking I/O makes callback hell
    • Callable makes deep nest, lambda is not solution for it
    • CompletableFuture is better solution, have a try with it
    • similar with Promise in JavaScript
    • It works with @Async in Spring Framework
    11

    View Slide

  12. CONCLUSION
    • We need to consider how to handle necessary state and mutability,
    with considering better async method handling.

    • To consider them simply, we need a paradigm shift in your mind.
    12

    View Slide

  13. YOU ARE NOT CODING A PROCEDURE!
    13

    View Slide

  14. WHAT YOUR PROGRAM IS?
    • We learned that program runs from top to bottom in your editor
    • in context of structured programming just has sequence,
    selection, and repetition
    14

    View Slide

  15. SEQUENCIAL
    PROCEDURE
    example: A traditional web app
    that displays post and widget
    15
    load user
    load post
    combine data
    persist combined data
    load widget
    render

    View Slide

  16. SEQUENCIAL
    PROCEDURE
    example: A traditional web app
    that displays post and widget
    16
    load user
    load post
    combine data
    persist combined data
    load widget
    render
    Why we don’t start loading before
    persisting combined data?
    why don’t we load user and post in
    parallel?

    View Slide

  17. HOW ABOUT MULTI-THREAD APP?
    • You pass value/message to another thread,
    • You wait until other threads finish their task, and
    • You zip (combine) them to start a task in another thread.

    • You may need to care which thread we run each task (e.g. UI thread)
    17

    View Slide

  18. DIRECTED
    ACYCLIC
    GRAPH
    Each task has dependency on others,
    waits until dependee gives data.
    18

    View Slide

  19. DIRECTED
    ACYCLIC
    GRAPH
    Each task has dependency on others,
    waits until dependee gives data.
    19
    Thread 1 Thread 2
    Thread 3
    similar with MapReduce?

    View Slide

  20. HOW TO CODE A GRAPH?
    • Wire relation between tasks (lambda or method)
    • Keep tasks stateless, idempotence and thread safe
    • Prefer CompletableFuture than Callable
    • Encapsulate state/mutability in each task
    • disclose immutable data to others
    20

    View Slide

  21. ROUGH SAMPLE CODE
    21
    with JDK8 API

    View Slide

  22. NOT SO PRODUCTIVE…
    • How to specify the thread to run tasks?
    • How to handle the exception in tasks?
    • How to make implementation testable?
    • How to cache, concat, filter, group, retry and throttle data?
    22

    View Slide

  23. CONCLUSION
    • Multi-thread app is not a procedure but a graph
    • Wire tasks that encapsulate mutability in it
    • JDK8 provides CompletableFuture and it fulfills a part of
    requirements
    23

    View Slide

  24. PROJECT REACTOR
    THE LATEST APPROACH
    24

    View Slide

  25. EXISTING APPROACH
    • We have many approaches like…
    • Rx.NET, Akka-streams, RxJava and Project Reactor (ref for diff)
    • JDK9 Flow could be standard in future
    • Project Reactor is most flesh and well-integrated with Spring
    25

    View Slide

  26. BEFORE DIVING REACTOR…
    • Summarize existing problems:
    • How to specify the thread to run tasks?
    • How to handle the exception in tasks?
    • How to make implementation testable?
    • How to cache, concat, filter, group, retry and throttle data?
    26

    View Slide

  27. THREAD HANDLING
    • Scheduler helps you to decide which thread to run tasks
    • Schedulers.parallel() for non-blocking tasks, to use fixed size thread
    pool.
    • Schedulers.elastic() for blocking tasks (JDBC etc.), to launch new
    thread if necessary.
    27

    View Slide

  28. THREAD HANDLING
    • Set scheduler by Flux#publishOn() and Flux#subscribeOn()
    28

    View Slide

  29. THREAD HANDLING
    • Set scheduler by Flux#publishOn() and Flux#subscribeOn()
    29
    published on parallel-1
    published on parallel-1
    published on parallel-1
    published on parallel-1
    published on parallel-1
    :
    :

    View Slide

  30. THREAD HANDLING
    • To run task in multiple thread, use Flux#parallel()
    30

    View Slide

  31. THREAD HANDLING
    • To run task in multiple thread, use Flux#parallel()
    31
    run on parallel-1
    run on parallel-2
    run on parallel-3
    run on parallel-3
    run on parallel-4
    :
    :

    View Slide

  32. BEFORE DIVING REACTOR…
    • Summarize existing problems:
    • How to specify the thread to run tasks?
    • How to handle the exception in tasks?
    • How to make implementation testable?
    • How to cache, concat, filter, group, retry and throttle data?
    32

    View Slide

  33. EXCEPTION HANDLING
    • Each task (e.g. map, reduce, filter) can throw exception
    33

    View Slide

  34. EXCEPTION HANDLING
    • Or return Flux.error() in Flux#flatMap()
    34

    View Slide

  35. BEFORE DIVING REACTOR…
    • Summarize existing problems:
    • How to specify the thread to run tasks?
    • How to handle the exception in tasks?
    • How to make implementation testable?
    • How to cache, concat, filter, group, retry and throttle data?
    35

    View Slide

  36. TASK IS ENOUGH TESTABLE
    • It’s just a lambda or method
    • Key is how to test the scenario realized by graph, the connected tasks
    36

    View Slide

  37. USE REACTOR-TEST
    • StepVerifier in reactor-test helps you
    37

    View Slide

  38. BEFORE DIVING REACTOR…
    • Summarize existing problems:
    • How to specify the thread to run tasks?
    • How to handle the exception in tasks?
    • How to make implementation testable?
    • How to cache, concat, filter, group, retry and throttle data?
    38

    View Slide

  39. PUBLISHERS PROVIDES
    CONVENIENCE WAY
    • cache() to reuse emitted signals for further Subscribers
    • concat() Subscribers to make single subscriber
    • filter() source value before emit it (same with Stream API)
    • groupBy() some key, to make multiple publishers (similar with groupingBy collector)
    • retry() subscribe when subscribers throw error
    • for throttling, sampleTimeout() could be help
    39

    View Slide

  40. PUBLISHERS PROVIDES
    CONVENIENCE WAY
    • We cannot use try-with-resources to close resource
    • because finally block will be executed before resource is used at
    timing to subscribe
    • use Flux.using() instead
    40

    View Slide

  41. CAN WE USE PROJECT REACTOR
    IN PRODUCTION?
    41

    View Slide

  42. THREE USE CASES
    • Web application
    • CLI application
    • GUI application
    42

    View Slide

  43. WEB APPLICATION
    • Use spring-webflux with spring-boot
    • New web application framework based on Project Reactor
    • My sandbox project: javadocky
    43

    View Slide

  44. KNOWN LIMITATION OF WEBFLUX
    • Community still needs time to support webflux
    • Actuator (monitoring) : done
    • Springfox (Swagger): not yet
    • We have sample project depending on snapshot
    • Validation: not yet for functional endpoint (or apply hack like this)
    44

    View Slide

  45. CLI APPLICATION
    • Simply use Project Reactor on spring-boot
    • My sandbox project: DependJ
    • CommandLineRunner helps you to touch raw command line parameter
    • ApplicationRunner helps you to handle command line parameter
    • You can simplify code to run tasks in parallel
    45

    View Slide

  46. GUI APPLICATION
    • Use project-reactor with reactor-extra on spring-boot
    • reactor-extra provides schedulers for event dispatch thread
    • like RxJava for Android app, we can use project reactor to separate
    backend computation and frontend operation
    46

    View Slide

  47. WRAP-UP
    47

    View Slide

  48. CHANGE MIND TO CODE A GRAPH
    • To code multi-thread app,
    • Encapsulate mutability into task,
    • Wire tasks by Project Reactor, then
    • Your app will be high-performance, non-blocking and testable!
    48

    View Slide

  49. Q&A
    49

    View Slide

  50. APPENDIX
    50

    View Slide

  51. WHAT REACTIVE PROGRAMMING IS?
    • Reactive Programming is a paradigm focuses on dataflow, and what I
    explained partially in this slide
    • Spread sheet like Excel provides reactive feature (Wikipedia)
    • “=B1+C1” will be updated when B1 and/or C1 is changed
    51

    View Slide

  52. THIS PARADIGM IS
    NOT ONLY FOR MULTI-THREAD APP
    • We can apply it to MSA & distributed service
    • Project Reactor provides backpressure
    • Reactive Systems (that can be achieved by Reactive Streams) can
    make distributed system responsive, elastic, resilient and message
    driven.
    52

    View Slide

  53. RELATED KEY WORDS
    • Reactive Streams, Reactive Systems and Reactive Programming
    • Idempotence, Stateless, Reentrant, Hysteresis
    53

    View Slide