Programmation réactive
avec Spring 5 et Reactor
Florian Beaufumé
11/2017
Florian Beaufumé
• Architecte logiciel
• Expert Java
• Freelance
• @fbeaufume
• www.adeliosys.fr
• www.slideshare.net/fbeaufume/presentations
• www.brownbaglunch.fr/baggers.html#florian-beaufume
• Montée en charge
• C10K (= 10K connexions)
• Comment supporter
10000 connexions simultanées ?
• Robustesse
• Que faire si la base ou les systèmes tiers
sont (très) lents ?
Objectifs
Server
DB
• Modèle standard de nos serveurs
• Est bloquant avec pool de thread :
• En charge :
• Multiplier les serveurs ?
• Multiplier les threads ?
Modèle « thread-per-request »
Server
Requests Threads pool
• Cout mémoire et CPU (context switches)
• Contention
Limitations des threads
Server thread DatabaseClient
HTTP request
SQL request #1
SQL request #2
• Montée en charge et robustesse
• Exemples : Node.js, Vert.x, Redis, HAProxy
Modèle non bloquant
Event queueEvents
Event loop
HTTP requests
SQL responses
…
Few worker threads
Callback hell
Exemple Spring 5
Types réactifs
Eléments Bloquant Réactif
0..N Collection<Book> Flux<Book>
0..1 Book Mono<Book>
0 void Mono<Void>
WebClient
Spring Framework 5
Spring Framework
Tomcat Netty
Reactor
Spring Web MVC Spring WebFlux
Bloquant Réactif
Reactive
Streams
Ecosystème Spring réactif
Spring Framework 5
Spring Boot 2
Spring Data 2
Spring Security 5
Spring Integration 5
Spring Cloud
Spring Data 2
• "Programming with asynchronous data streams"
• Basé sur des étapes asynchrones et non bloquantes
• API orientées callback et/ou déclaratives par composition de fonctions
• Programmation réactive ≈ streams + CompletableFuture + backpressure
• Bénéfices :
• Montée en charge
• Robustesse
Programmation réactive
• Code
• Logs
Reactor
Construction
Opérateurs
Marble diagrams
• Pour donner du contrôle au consommateur sur le producteur
Backpressure
Producer Consumer
Data flow
Data request
Conversions
• Cas simple
• Manipulation de l’échelle de temps
Tests avec reactor-test
• "Standard for asynchronous stream processing with non-blocking
backpressure"
• Implémentations : RxJava, Reactor, Akka Streams, etc.
Reactive streams
Comparaison de performance
VS
Bloquant
Réactif
Scénario
Time
Concurrent
users
2 min10 sec
http://localhost:8080/pause/1000
Charge
Bloquant Réactif
300 users injectés => 189 req/s mesuré 3000 users injectés => 2664 req/s mesuré
Temps de réponse
Bloquant Réactif
Moyenne=1462, médiane=1579, σ=297 Moyenne=1036, médiane=1013, σ=59
Threads
Bloquant Réactif
• Syntaxe déroutante
• Commencer par les streams Java 8 et la programmation fonctionnelle
• API contaminante
• Plus facile pour de nouvelles applications ou microservices
Difficultés
• JDBC pas encore supporté
• Mono.fromCallable(() -> { … }).subscribeOn(Schedulers.elastic())
• Attendre JDK 10
• ThreadLocal perdent leur intérêt (MDC logging par exemple)
• Pas encore de scope request ou session
• myFlux.subscriberContext(Context.of("key", "value"))…
Limitations
• Supporter une forte charge
• Pour fiabiliser des applications très communicantes
• Microservices
• Applications sensibles à la contention
Cas d’usages
@fbeaufume
www.adeliosys.fr
fr.slideshare.net/fbeaufume
Merci

Programmation réactive avec Spring 5 et Reactor