Slide 1

Slide 1 text

PROJECT REACTOR 2018-09-12 Kengo TODA 1

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

YOU ARE NOT CODING A PROCEDURE! 13

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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?

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

ROUGH SAMPLE CODE 21 with JDK8 API

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

PROJECT REACTOR THE LATEST APPROACH 24

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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 : :

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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 : :

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

CAN WE USE PROJECT REACTOR IN PRODUCTION? 41

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

WRAP-UP 47

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

Q&A 49

Slide 50

Slide 50 text

APPENDIX 50

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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