SlideShare a Scribd company logo
Por: Wellington
Macedo
Introdução à
Spring Web Flux
Por: Wellington
Vulgo: Lelim, Oesli
ou Jão
● O que é Spring WebFlux?
● Reactive Programming
● Reactive Stream
○ Reactor
● Arquitetura do WebFlux
● Aplicação de Exemplo
● Non-blocking IO vs Blocking IO
● Event loop
● Vantagens
● Desvantagens
● Referências
Agenda
O que é Spring Web Flux
● É um projeto do Spring!
● Fornece suporte para programação reativa na camada Web do Spring
● Chegou na versão 5.0 do Spring (2017)
AH NÃO BRINCA WELLINGTON
😒
Reactive Programming
É um paradigma de programação
Reactive Programming
PUB/SUB
Reactive Programming
Vamos ver a aplicação rodando!
Reactive Programming
interface Consumer<T> {
fun consume(command: T)
}
Reactive Programming
class Publisher<T> {
private val consumers = mutableListOf<Consumer<T>>()
fun subscribe(consumer: Consumer<T>) {
consumers.add(consumer)
}
fun publish(value: T) = consumers.forEach { consumer -> consume.consume(value) }
}
Reactive Programming
class Publisher<T> {
private val consumers = mutableListOf<Consumer<T>>()
fun subscribe(consumer: Consumer<T>) {
consumers.add(consumer)
}
fun publish(value: T) = consumers.forEach { consumer -> consumer.consume(value) }
}
Reactive Programming
class Publisher<T> {
private val consumers = mutableListOf<Consumer<T>>()
fun subscribe(consumer: Consumer<T>) {
consumers.add(consumer)
}
fun publish(value: T) = consumers.forEach { consumer -> consumer.consume(value) }
}
Reactive Programming
class Publisher<T> {
private val consumers = mutableListOf<Consumer<T>>()
fun subscribe(consumer: Consumer<T>) {
consumers.add(consumer)
}
fun publish(value: T) = consumers.forEach { consumer -> consumer.consume(value) }
}
Reactive Programming
class CommandExecutor : Consumer<Int> {
override fun consume(command: Int) {
val resp = when (command) {
1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA"
2 -> "Figueira né feio"
3 -> throw FinishProgram()
else -> "Essa opção não existe feio"
}
println("Resposta: $resp")
}
}
Reactive Programming
class CommandExecutor : Consumer<Int> {
override fun consume(command: Int) {
val resp = when (command) {
1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA"
2 -> "Figueira né feio"
3 -> throw FinishProgram()
else -> "Essa opção não existe feio"
}
println("Resposta: $resp")
}
}
Reactive Programming
class CommandExecutor : Consumer<Int> {
override fun consume(command: Int) {
val resp = when (command) {
1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA"
2 -> "Figueira né feio"
3 -> throw FinishProgram()
else -> "Essa opção não existe feio"
}
println("Resposta: $resp")
}
}
Reactive Programming
class CommandExecutor : Consumer<Int> {
override fun consume(command: Int) {
val resp = when (command) {
1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA"
2 -> "Figueira né feio"
3 -> throw FinishProgram()
else -> "Essa opção não existe feio"
}
println("Resposta: $resp")
}
}
Reactive Programming
class CommandExecutor : Consumer<Int> {
override fun consume(command: Int) {
val resp = when (command) {
1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA"
2 -> "Figueira né feio"
3 -> throw FinishProgram()
else -> "Essa opção não existe feio"
}
println("Resposta: $resp")
}
}
Reactive Programming
class CommandLogger : Consumer<Int> {
private val logs = mutableListOf<String>()
override fun consume(command: Int) = log(command)
private fun log(command: Int) {
logs.add("[${now()}] command $command")
}
fun printLogs() = logs.forEach(::println)
}
Reactive Programming
class CommandLogger : Consumer<Int> {
private val logs = mutableListOf<String>()
override fun consume(command: Int) = log(command)
private fun log(command: Int) {
logs.add("[${now()}] command $command")
}
fun printLogs() = logs.forEach(::println)
}
Reactive Programming
class CommandLogger : Consumer<Int> {
private val logs = mutableListOf<String>()
override fun consume(command: Int) = log(command)
private fun log(command: Int) {
logs.add("[${now()}] command $command")
}
fun printLogs() = logs.forEach(::println)
}
Reactive Programming
class CommandLogger : Consumer<Int> {
private val logs = mutableListOf<String>()
override fun consume(command: Int) = log(command)
private fun log(command: Int) {
logs.add("[${now()}] command $command")
}
fun printLogs() = logs.forEach(::println)
}
Reactive Programming
class CommandLogger : Consumer<Int> {
private val logs = mutableListOf<String>()
override fun consume(command: Int) = log(command)
private fun log(command: Int) {
logs.add("[${now()}] command $command")
}
fun printLogs() = logs.forEach(::println)
}
Reactive Programming
class CommandLogger : Consumer<Int> {
private val logs = mutableListOf<String>()
override fun consume(command: Int) = log(command)
private fun log(command: Int) {
logs.add("[${now()}] command $command")
}
fun printLogs() = logs.forEach(::println)
}
Reactive Programming
fun main() {
val publisher = Publisher<Int>()
val commandLogger = CommandLogger()
val commandExecutor = CommandExecutor()
publisher.subscribe(commandLogger)
publisher.subscribe(commandExecutor)
try {
val read = Scanner(System.`in`)
while (true) {
menu()
print("Digite a opção desejada: ")
val command = read.nextInt()
publisher.publish(command)
}
} catch (e: FinishProgram) {
println("Comandos executados: ")
commandLogger.printLogs()
print("Encerrando o programa!")
}
}
Reactive Programming
fun main() {
val publisher = Publisher<Int>()
val commandLogger = CommandLogger()
val commandExecutor = CommandExecutor()
publisher.subscribe(commandLogger)
publisher.subscribe(commandExecutor)
try {
val read = Scanner(System.`in`)
while (true) {
menu()
print("Digite a opção desejada: ")
val command = read.nextInt()
publisher.publish(command)
}
} catch (e: FinishProgram) {
println("Comandos executados: ")
commandLogger.printLogs()
print("Encerrando o programa!")
}
}
Reactive Programming
fun main() {
val publisher = Publisher<Int>()
val commandLogger = CommandLogger()
val commandExecutor = CommandExecutor()
publisher.subscribe(commandLogger)
publisher.subscribe(commandExecutor)
try {
val read = Scanner(System.`in`)
while (true) {
menu()
print("Digite a opção desejada: ")
val command = read.nextInt()
publisher.publish(command)
}
} catch (e: FinishProgram) {
println("Comandos executados: ")
commandLogger.printLogs()
print("Encerrando o programa!")
}
}
Reactive Programming
fun main() {
val publisher = Publisher<Int>()
val commandLogger = CommandLogger()
val commandExecutor = CommandExecutor()
publisher.subscribe(commandLogger)
publisher.subscribe(commandExecutor)
try {
val read = Scanner(System.`in`)
while (true) {
menu()
print("Digite a opção desejada: ")
val command = read.nextInt()
publisher.publish(command)
}
} catch (e: FinishProgram) {
println("Comandos executados: ")
commandLogger.printLogs()
print("Encerrando o programa!")
}
}
Reactive Programming
fun main() {
val publisher = Publisher<Int>()
val commandLogger = CommandLogger()
val commandExecutor = CommandExecutor()
publisher.subscribe(commandLogger)
publisher.subscribe(commandExecutor)
try {
val read = Scanner(System.`in`)
while (true) {
menu()
print("Digite a opção desejada: ")
val command = read.nextInt()
publisher.publish(command)
}
} catch (e: FinishProgram) {
println("Comandos executados: ")
commandLogger.printLogs()
print("Encerrando o programa!")
}
}
Reactive Programming
fun main() {
val publisher = Publisher<Int>()
val commandLogger = CommandLogger()
val commandExecutor = CommandExecutor()
publisher.subscribe(commandLogger)
publisher.subscribe(commandExecutor)
try {
val read = Scanner(System.`in`)
while (true) {
menu()
print("Digite a opção desejada: ")
val command = read.nextInt()
publisher.publish(command)
}
} catch (e: FinishProgram) {
println("Comandos executados: ")
commandLogger.printLogs()
print("Encerrando o programa!")
}
}
Reactive Programming
fun main() {
val publisher = Publisher<Int>()
val commandLogger = CommandLogger()
val commandExecutor = CommandExecutor()
publisher.subscribe(commandLogger)
publisher.subscribe(commandExecutor)
try {
val read = Scanner(System.`in`)
while (true) {
menu()
print("Digite a opção desejada: ")
val command = read.nextInt()
publisher.publish(command)
}
} catch (e: FinishProgram) {
println("Comandos executados: ")
commandLogger.printLogs()
print("Encerrando o programa!")
}
}
Reactive Programming
fun main() {
val publisher = Publisher<Int>()
val commandLogger = CommandLogger()
val commandExecutor = CommandExecutor()
publisher.subscribe(commandLogger)
publisher.subscribe(commandExecutor)
try {
val read = Scanner(System.`in`)
while (true) {
menu()
print("Digite a opção desejada: ")
val command = read.nextInt()
publisher.publish(command)
}
} catch (e: FinishProgram) {
println("Comandos executados: ")
commandLogger.printLogs()
print("Encerrando o programa!")
}
}
Reactive Programming
Reagimos aos comandos publicados!
Reactive Programming
Zero acoplamento entre diferentes consumers!
Reactive Stream
É uma especificação!
● O que quer dizer especificação?
● Para o que serve essa especificação?
Reactive Stream
Reactive Stream
Reactive Stream
Reactive Stream
Reactive Stream
Reactive Stream
Reactive Stream
Reactive Stream
Reactive Stream
Reactive Stream
Reactive Stream
Reactor
Publishers
Reactor
● Mono 0..1
0..infinito● Flux
Reactor
Exemplos
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.subscribe { value -> print(value) /* consumer */ }
// Imprime: Goku>Naruto
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.subscribe { value -> print(value) /* consumer */ }
// Imprime: Goku>Naruto
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.subscribe { value -> print(value) /* consumer */ }
// Imprime: Goku>Naruto
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.subscribe { value -> print(value) /* consumer */ }
// Imprime: Goku>Naruto
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.map(String::toUpperCase)
.map { value -> if(value == ">") "<" else value }
.subscribe { value -> print(value) /* consumer */ }
// Imprime: GOKU<NARUTO
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.map(String::toUpperCase)
.map { value -> if(value == ">") "<" else value }
.subscribe { value -> print(value) /* consumer */ }
// Imprime: GOKU<NARUTO
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.map(String::toUpperCase)
.map { value -> if(value == ">") "<" else value }
.subscribe { value -> print(value) /* consumer */ }
// Imprime: GOKU<NARUTO
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.map(String::toUpperCase)
.map { value -> if(value == ">") "<" else value }
.subscribe { value -> print(value) /* consumer */ }
// Imprime: GOKU<NARUTO
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.map(String::toUpperCase)
.map { value -> if(value == ">") "<" else value }
.subscribe { value -> print(value) /* consumer */ }
// Imprime: GOKU<NARUTO
Reactor
val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto"))
publisher.map(String::toUpperCase)
.map { value -> if(value == ">") "<" else value }
.subscribe { value -> print(value) /* consumer */ }
// Imprime: GOKU<NARUTO
Reactor
val monoPublisher = Mono.just("Goku is the best!")
monoPublisher.subscribeOn(Schedulers.parallel())
.subscribe { print("[${Thread.currentThread().name}] $it") }
println("[${Thread.currentThread().name}] Who is the best?")
// Imprime: [main] Who is the best?
// [parallel-1] Goku is the best!
Reactor
val monoPublisher = Mono.just("Goku is the best!")
monoPublisher.subscribeOn(Schedulers.parallel())
.subscribe { print("[${Thread.currentThread().name}] $it") }
println("[${Thread.currentThread().name}] Who is the best?")
// Imprime: [main] Who is the best?
// [parallel-1] Goku is the best!
Reactor
val monoPublisher = Mono.just("Goku is the best!")
monoPublisher.subscribeOn(Schedulers.parallel())
.subscribe { print("[${Thread.currentThread().name}] $it") }
println("[${Thread.currentThread().name}] Who is the best?")
// Imprime: [main] Who is the best?
// [parallel-1] Goku is the best!
Reactor
val monoPublisher = Mono.just("Goku is the best!")
monoPublisher.subscribeOn(Schedulers.parallel())
.subscribe { print("[${Thread.currentThread().name}] $it") }
println("[${Thread.currentThread().name}] Who is the best?")
// Imprime: [main] Who is the best?
// [parallel-1] Goku is the best!
Reactor
val monoPublisher = Mono.just("Goku is the best!")
monoPublisher.subscribeOn(Schedulers.parallel())
.subscribe { print("[${Thread.currentThread().name}] $it") }
println("[${Thread.currentThread().name}] Who is the best?")
// Imprime: [main] Who is the best?
// [parallel-1] Goku is the best!
Reactor
val monoPublisher = Mono.just("Goku is the best!")
monoPublisher.subscribeOn(Schedulers.parallel())
.subscribe { print("[${Thread.currentThread().name}] $it") }
println("[${Thread.currentThread().name}] Who is the best?")
// Imprime: [main] Who is the best?
// [parallel-1] Goku is the best!
Arquitetura do Webflux
@Controller, @RequestMapping Router functions
spring-webflux
HTTP / Reactive Streams
Tomcat, Jetty, Netty,
Undertow
spring-webmvc
Servlet API
Servlet Container
Webflux
Talk is cheap, show me the code!
Blocking IO
Thread
Waiting
Running
Blocking IO
Thread
Waiting
Running
Blocking IO
Thread
Waiting
Running
Chamada ao
database
Blocking IO
IO Operation
Thread
Waiting
Running
Chamada ao
database
Blocking IO
IO Operation
Thread
Waiting
Running
Resposta do
database
Blocking IO
IO Operation
Thread
Waiting
Running
Resposta do
database
Non-blocking IO
Thread
Running
Kernel Process
Non-blocking IO
Thread
Running
Kernel Process
Non-blocking IO
Thread
Running
Kernel Process Chamada ao
database
Non-blocking IO
IO Operation
Thread
Running
Kernel Process
Thread sendo
aproveitada para
outros processos
Non-blocking IO
IO Operation
Thread
Running
Kernel Process Resposta do
database
Non-blocking IO
IO Operation
Thread
Running
Kernel Process
Event loop
É um design pattern!
Event loop
Event Queue
Event loop
Event Queue
Event loop
Event Loop
Thread
Event Queue
Event loop
Event Loop
Thread
Event Queue
Event loop
Event Loop
Thread
Event Queue
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
class EventLoop(private val eventQueue: BlockingQueue<Runnable>) {
init {
start()
}
private fun start() {
Thread(Runnable {
var task = eventQueue.take()
while (true) {
task.run()
task = eventQueue.take()
}
}).start()
}
fun put(task: Runnable) {
eventQueue.put(task)
}
}
Event loop
E se for necessário conectar com o DB ou ler um
arquivo, isso não vai bloquear o Event Loop?
Event loop
Event Loop
Kernel
Thread
Event Queue
Event loop
Event Loop
Non-blocking
ops
Kernel
Thread
Event Queue
Event loop
Event Loop
Non-blocking
ops
Kernel
Thread
Event Queue
put(event)
Event loop - NIO Libs
● R2DBC - Reactive Relational Database Connectivity
● Web Client
● Reactor Netty (UDP, TCP, HTTP)
Event loop
E se caso essa rotina for estritamente
bloqueante? Por exemplo, uma que use muito
CPU Bound. O que deve ser feito?
Event loop
Event Loop
Worker
Thread Pool
Event Queue
Thread
Event loop
Event Loop
Blocking Ops
Worker
Thread Pool
Event Queue
Thread
Event loop
Event Loop
Blocking Ops
Worker
Thread Pool
Event Queue
Thread
put(event)
Event Loop - CPU Bound exemplo
fun doHeavyProcess() {
println("running other spring boot application rs")
}
Event Loop - CPU Bound exemplo
@PostMapping("/heavy-process")
fun heavyProcess(): Mono<ResponseEntity<Nothing>> {
return Mono
.defer { Mono.justOrEmpty(::doHeavyProcess) }
.subscribeOn(Schedulers.parallel())
.map { ResponseEntity.ok().build<Nothing>() }
}
Event Loop - CPU Bound exemplo
@PostMapping("/heavy-process")
fun heavyProcess(): Mono<ResponseEntity<Nothing>> {
return Mono
.defer { Mono.justOrEmpty(::doHeavyProcess) }
.subscribeOn(Schedulers.parallel())
.map { ResponseEntity.ok().build<Nothing>() }
}
Event Loop - CPU Bound exemplo
@PostMapping("/heavy-process")
fun heavyProcess(): Mono<ResponseEntity<Nothing>> {
return Mono
.defer { Mono.justOrEmpty(::doHeavyProcess) }
.subscribeOn(Schedulers.parallel())
.map { ResponseEntity.ok().build<Nothing>() }
}
Event Loop - CPU Bound exemplo
@PostMapping("/heavy-process")
fun heavyProcess(): Mono<ResponseEntity<Nothing>> {
return Mono
.defer { Mono.justOrEmpty(::doHeavyProcess) }
.subscribeOn(Schedulers.parallel())
.map { ResponseEntity.ok().build<Nothing>() }
}
Vantagens e Desvantagens
Disclaimer
+ Utiliza melhor os recursos do hardware
+ Alta disponibilidade
Vantagens
- Codebase mais complexo
- É mais complexo para debugar
- Suposições erradas podem bloquear todo o servidor
- Não trabalha com thread local
- Logs
- Telemetria
- Stack Traces podem se tornar inúteis
Desvantagens
Referências
● https://medium.com/@rarepopa_68087/reactive-programming-with-spring-boot-and-webflux-734086f8c8a5
● https://tanzu.vmware.com/content/slides/reactive-applications-on-apache-tomcat-and-servlet-3-1-containers
● https://blog.codecentric.de/en/2019/04/explain-non-blocking-i-o-like-im-five/
● https://www.youtube.com/watch?v=2oXqbLhMS_A
● https://medium.com/ing-blog/how-does-non-blocking-io-work-under-the-hood-6299d2953c74
● https://www.scnsoft.com/blog/java-reactive-programming
● https://www.slideshare.net/kslisenko/networking-in-java-with-nio-and-netty-76583794
● https://www.reactivemanifesto.org/glossary#Non-Blocking
● https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html
● https://dzone.com/articles/spring-webflux-eventloop-vs-thread-per-request-mod
● https://www.reactive-streams.org/
● https://projectreactor.io/docs/core/release/reference/
● http://tutorials.jenkov.com/netty/overview.html
Códigos de exemplo
https://github.com/wellington3110/webfluxpresentation
!!!
/wellington3110
/in/wgmacedo/
wellingtongustavomacedo@gmail.com
Wellington Gustavo Macedo

More Related Content

What's hot

Oop assignment 02
Oop assignment 02Oop assignment 02
Oop assignment 02
MamoonKhan39
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix Task
Hermann Hueck
 
Assignment no39
Assignment no39Assignment no39
Assignment no39Jay Patel
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in Scala
Hermann Hueck
 
Programa en C++ ( escriba 3 números y diga cual es el mayor))
Programa en C++ ( escriba 3 números y diga cual es el mayor))Programa en C++ ( escriba 3 números y diga cual es el mayor))
Programa en C++ ( escriba 3 números y diga cual es el mayor))Alex Penso Romero
 
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
Продвинутая отладка JavaScript с помощью Chrome Dev ToolsПродвинутая отладка JavaScript с помощью Chrome Dev Tools
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
FDConf
 
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Codemotion
 

What's hot (7)

Oop assignment 02
Oop assignment 02Oop assignment 02
Oop assignment 02
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix Task
 
Assignment no39
Assignment no39Assignment no39
Assignment no39
 
Implementing the IO Monad in Scala
Implementing the IO Monad in ScalaImplementing the IO Monad in Scala
Implementing the IO Monad in Scala
 
Programa en C++ ( escriba 3 números y diga cual es el mayor))
Programa en C++ ( escriba 3 números y diga cual es el mayor))Programa en C++ ( escriba 3 números y diga cual es el mayor))
Programa en C++ ( escriba 3 números y diga cual es el mayor))
 
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
Продвинутая отладка JavaScript с помощью Chrome Dev ToolsПродвинутая отладка JavaScript с помощью Chrome Dev Tools
Продвинутая отладка JavaScript с помощью Chrome Dev Tools
 
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
 

Similar to Introdução à Spring Web Flux

USER DEFINE FUNCTIONS IN PYTHON
USER DEFINE FUNCTIONS IN PYTHONUSER DEFINE FUNCTIONS IN PYTHON
USER DEFINE FUNCTIONS IN PYTHON
vikram mahendra
 
Effecting Pure Change - How anything ever gets done in functional programming...
Effecting Pure Change - How anything ever gets done in functional programming...Effecting Pure Change - How anything ever gets done in functional programming...
Effecting Pure Change - How anything ever gets done in functional programming...
Tech Triveni
 
Asynchronous Programming at Netflix
Asynchronous Programming at NetflixAsynchronous Programming at Netflix
Asynchronous Programming at Netflix
C4Media
 
Developer Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoDeveloper Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duo
The Software House
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languages
Rafael Winterhalter
 
Functional Programming in Java - Code for Maintainability
Functional Programming in Java - Code for MaintainabilityFunctional Programming in Java - Code for Maintainability
Functional Programming in Java - Code for Maintainability
Marcin Stepien
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
Ganesh Samarthyam
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
Michiel Borkent
 
What's in Groovy for Functional Programming
What's in Groovy for Functional ProgrammingWhat's in Groovy for Functional Programming
What's in Groovy for Functional Programming
Naresha K
 
Monads in Swift
Monads in SwiftMonads in Swift
Monads in Swift
Vincent Pradeilles
 
Closures
ClosuresClosures
Closures
prashanthbabu07
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in Scala
Wiem Zine Elabidine
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
Ignacio Martín
 
golang_getting_started.pptx
golang_getting_started.pptxgolang_getting_started.pptx
golang_getting_started.pptx
Guy Komari
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
Ignacio Martín
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
Tor Ivry
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
Bo-Yi Wu
 
Un dsl pour ma base de données
Un dsl pour ma base de donnéesUn dsl pour ma base de données
Un dsl pour ma base de données
Romain Lecomte
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android application
Seven Peaks Speaks
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeLambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive Code
Ian Robertson
 

Similar to Introdução à Spring Web Flux (20)

USER DEFINE FUNCTIONS IN PYTHON
USER DEFINE FUNCTIONS IN PYTHONUSER DEFINE FUNCTIONS IN PYTHON
USER DEFINE FUNCTIONS IN PYTHON
 
Effecting Pure Change - How anything ever gets done in functional programming...
Effecting Pure Change - How anything ever gets done in functional programming...Effecting Pure Change - How anything ever gets done in functional programming...
Effecting Pure Change - How anything ever gets done in functional programming...
 
Asynchronous Programming at Netflix
Asynchronous Programming at NetflixAsynchronous Programming at Netflix
Asynchronous Programming at Netflix
 
Developer Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoDeveloper Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duo
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languages
 
Functional Programming in Java - Code for Maintainability
Functional Programming in Java - Code for MaintainabilityFunctional Programming in Java - Code for Maintainability
Functional Programming in Java - Code for Maintainability
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
What's in Groovy for Functional Programming
What's in Groovy for Functional ProgrammingWhat's in Groovy for Functional Programming
What's in Groovy for Functional Programming
 
Monads in Swift
Monads in SwiftMonads in Swift
Monads in Swift
 
Closures
ClosuresClosures
Closures
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in Scala
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
golang_getting_started.pptx
golang_getting_started.pptxgolang_getting_started.pptx
golang_getting_started.pptx
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
 
Un dsl pour ma base de données
Un dsl pour ma base de donnéesUn dsl pour ma base de données
Un dsl pour ma base de données
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android application
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeLambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive Code
 

Recently uploaded

A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
sonjaschweigert1
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Assure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyesAssure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
Peter Spielvogel
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
Vlad Stirbu
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 

Recently uploaded (20)

A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Assure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyesAssure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyes
 
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 

Introdução à Spring Web Flux

  • 1. Por: Wellington Macedo Introdução à Spring Web Flux Por: Wellington Vulgo: Lelim, Oesli ou Jão
  • 2. ● O que é Spring WebFlux? ● Reactive Programming ● Reactive Stream ○ Reactor ● Arquitetura do WebFlux ● Aplicação de Exemplo ● Non-blocking IO vs Blocking IO ● Event loop ● Vantagens ● Desvantagens ● Referências Agenda
  • 3. O que é Spring Web Flux ● É um projeto do Spring! ● Fornece suporte para programação reativa na camada Web do Spring ● Chegou na versão 5.0 do Spring (2017) AH NÃO BRINCA WELLINGTON 😒
  • 4. Reactive Programming É um paradigma de programação
  • 6. Reactive Programming Vamos ver a aplicação rodando!
  • 7. Reactive Programming interface Consumer<T> { fun consume(command: T) }
  • 8. Reactive Programming class Publisher<T> { private val consumers = mutableListOf<Consumer<T>>() fun subscribe(consumer: Consumer<T>) { consumers.add(consumer) } fun publish(value: T) = consumers.forEach { consumer -> consume.consume(value) } }
  • 9. Reactive Programming class Publisher<T> { private val consumers = mutableListOf<Consumer<T>>() fun subscribe(consumer: Consumer<T>) { consumers.add(consumer) } fun publish(value: T) = consumers.forEach { consumer -> consumer.consume(value) } }
  • 10. Reactive Programming class Publisher<T> { private val consumers = mutableListOf<Consumer<T>>() fun subscribe(consumer: Consumer<T>) { consumers.add(consumer) } fun publish(value: T) = consumers.forEach { consumer -> consumer.consume(value) } }
  • 11. Reactive Programming class Publisher<T> { private val consumers = mutableListOf<Consumer<T>>() fun subscribe(consumer: Consumer<T>) { consumers.add(consumer) } fun publish(value: T) = consumers.forEach { consumer -> consumer.consume(value) } }
  • 12. Reactive Programming class CommandExecutor : Consumer<Int> { override fun consume(command: Int) { val resp = when (command) { 1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA" 2 -> "Figueira né feio" 3 -> throw FinishProgram() else -> "Essa opção não existe feio" } println("Resposta: $resp") } }
  • 13. Reactive Programming class CommandExecutor : Consumer<Int> { override fun consume(command: Int) { val resp = when (command) { 1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA" 2 -> "Figueira né feio" 3 -> throw FinishProgram() else -> "Essa opção não existe feio" } println("Resposta: $resp") } }
  • 14. Reactive Programming class CommandExecutor : Consumer<Int> { override fun consume(command: Int) { val resp = when (command) { 1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA" 2 -> "Figueira né feio" 3 -> throw FinishProgram() else -> "Essa opção não existe feio" } println("Resposta: $resp") } }
  • 15. Reactive Programming class CommandExecutor : Consumer<Int> { override fun consume(command: Int) { val resp = when (command) { 1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA" 2 -> "Figueira né feio" 3 -> throw FinishProgram() else -> "Essa opção não existe feio" } println("Resposta: $resp") } }
  • 16. Reactive Programming class CommandExecutor : Consumer<Int> { override fun consume(command: Int) { val resp = when (command) { 1 -> "Amaz... zueira é o Mercado Livre HAUAHUHUAAHUA" 2 -> "Figueira né feio" 3 -> throw FinishProgram() else -> "Essa opção não existe feio" } println("Resposta: $resp") } }
  • 17. Reactive Programming class CommandLogger : Consumer<Int> { private val logs = mutableListOf<String>() override fun consume(command: Int) = log(command) private fun log(command: Int) { logs.add("[${now()}] command $command") } fun printLogs() = logs.forEach(::println) }
  • 18. Reactive Programming class CommandLogger : Consumer<Int> { private val logs = mutableListOf<String>() override fun consume(command: Int) = log(command) private fun log(command: Int) { logs.add("[${now()}] command $command") } fun printLogs() = logs.forEach(::println) }
  • 19. Reactive Programming class CommandLogger : Consumer<Int> { private val logs = mutableListOf<String>() override fun consume(command: Int) = log(command) private fun log(command: Int) { logs.add("[${now()}] command $command") } fun printLogs() = logs.forEach(::println) }
  • 20. Reactive Programming class CommandLogger : Consumer<Int> { private val logs = mutableListOf<String>() override fun consume(command: Int) = log(command) private fun log(command: Int) { logs.add("[${now()}] command $command") } fun printLogs() = logs.forEach(::println) }
  • 21. Reactive Programming class CommandLogger : Consumer<Int> { private val logs = mutableListOf<String>() override fun consume(command: Int) = log(command) private fun log(command: Int) { logs.add("[${now()}] command $command") } fun printLogs() = logs.forEach(::println) }
  • 22. Reactive Programming class CommandLogger : Consumer<Int> { private val logs = mutableListOf<String>() override fun consume(command: Int) = log(command) private fun log(command: Int) { logs.add("[${now()}] command $command") } fun printLogs() = logs.forEach(::println) }
  • 23. Reactive Programming fun main() { val publisher = Publisher<Int>() val commandLogger = CommandLogger() val commandExecutor = CommandExecutor() publisher.subscribe(commandLogger) publisher.subscribe(commandExecutor) try { val read = Scanner(System.`in`) while (true) { menu() print("Digite a opção desejada: ") val command = read.nextInt() publisher.publish(command) } } catch (e: FinishProgram) { println("Comandos executados: ") commandLogger.printLogs() print("Encerrando o programa!") } }
  • 24. Reactive Programming fun main() { val publisher = Publisher<Int>() val commandLogger = CommandLogger() val commandExecutor = CommandExecutor() publisher.subscribe(commandLogger) publisher.subscribe(commandExecutor) try { val read = Scanner(System.`in`) while (true) { menu() print("Digite a opção desejada: ") val command = read.nextInt() publisher.publish(command) } } catch (e: FinishProgram) { println("Comandos executados: ") commandLogger.printLogs() print("Encerrando o programa!") } }
  • 25. Reactive Programming fun main() { val publisher = Publisher<Int>() val commandLogger = CommandLogger() val commandExecutor = CommandExecutor() publisher.subscribe(commandLogger) publisher.subscribe(commandExecutor) try { val read = Scanner(System.`in`) while (true) { menu() print("Digite a opção desejada: ") val command = read.nextInt() publisher.publish(command) } } catch (e: FinishProgram) { println("Comandos executados: ") commandLogger.printLogs() print("Encerrando o programa!") } }
  • 26. Reactive Programming fun main() { val publisher = Publisher<Int>() val commandLogger = CommandLogger() val commandExecutor = CommandExecutor() publisher.subscribe(commandLogger) publisher.subscribe(commandExecutor) try { val read = Scanner(System.`in`) while (true) { menu() print("Digite a opção desejada: ") val command = read.nextInt() publisher.publish(command) } } catch (e: FinishProgram) { println("Comandos executados: ") commandLogger.printLogs() print("Encerrando o programa!") } }
  • 27. Reactive Programming fun main() { val publisher = Publisher<Int>() val commandLogger = CommandLogger() val commandExecutor = CommandExecutor() publisher.subscribe(commandLogger) publisher.subscribe(commandExecutor) try { val read = Scanner(System.`in`) while (true) { menu() print("Digite a opção desejada: ") val command = read.nextInt() publisher.publish(command) } } catch (e: FinishProgram) { println("Comandos executados: ") commandLogger.printLogs() print("Encerrando o programa!") } }
  • 28. Reactive Programming fun main() { val publisher = Publisher<Int>() val commandLogger = CommandLogger() val commandExecutor = CommandExecutor() publisher.subscribe(commandLogger) publisher.subscribe(commandExecutor) try { val read = Scanner(System.`in`) while (true) { menu() print("Digite a opção desejada: ") val command = read.nextInt() publisher.publish(command) } } catch (e: FinishProgram) { println("Comandos executados: ") commandLogger.printLogs() print("Encerrando o programa!") } }
  • 29. Reactive Programming fun main() { val publisher = Publisher<Int>() val commandLogger = CommandLogger() val commandExecutor = CommandExecutor() publisher.subscribe(commandLogger) publisher.subscribe(commandExecutor) try { val read = Scanner(System.`in`) while (true) { menu() print("Digite a opção desejada: ") val command = read.nextInt() publisher.publish(command) } } catch (e: FinishProgram) { println("Comandos executados: ") commandLogger.printLogs() print("Encerrando o programa!") } }
  • 30. Reactive Programming fun main() { val publisher = Publisher<Int>() val commandLogger = CommandLogger() val commandExecutor = CommandExecutor() publisher.subscribe(commandLogger) publisher.subscribe(commandExecutor) try { val read = Scanner(System.`in`) while (true) { menu() print("Digite a opção desejada: ") val command = read.nextInt() publisher.publish(command) } } catch (e: FinishProgram) { println("Comandos executados: ") commandLogger.printLogs() print("Encerrando o programa!") } }
  • 31. Reactive Programming Reagimos aos comandos publicados!
  • 32. Reactive Programming Zero acoplamento entre diferentes consumers!
  • 33. Reactive Stream É uma especificação!
  • 34. ● O que quer dizer especificação? ● Para o que serve essa especificação? Reactive Stream
  • 43. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.subscribe { value -> print(value) /* consumer */ } // Imprime: Goku>Naruto
  • 44. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.subscribe { value -> print(value) /* consumer */ } // Imprime: Goku>Naruto
  • 45. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.subscribe { value -> print(value) /* consumer */ } // Imprime: Goku>Naruto
  • 46. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.subscribe { value -> print(value) /* consumer */ } // Imprime: Goku>Naruto
  • 47. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.map(String::toUpperCase) .map { value -> if(value == ">") "<" else value } .subscribe { value -> print(value) /* consumer */ } // Imprime: GOKU<NARUTO
  • 48. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.map(String::toUpperCase) .map { value -> if(value == ">") "<" else value } .subscribe { value -> print(value) /* consumer */ } // Imprime: GOKU<NARUTO
  • 49. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.map(String::toUpperCase) .map { value -> if(value == ">") "<" else value } .subscribe { value -> print(value) /* consumer */ } // Imprime: GOKU<NARUTO
  • 50. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.map(String::toUpperCase) .map { value -> if(value == ">") "<" else value } .subscribe { value -> print(value) /* consumer */ } // Imprime: GOKU<NARUTO
  • 51. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.map(String::toUpperCase) .map { value -> if(value == ">") "<" else value } .subscribe { value -> print(value) /* consumer */ } // Imprime: GOKU<NARUTO
  • 52. Reactor val publisher = Flux.fromArray(arrayOf("Goku", ">", "Naruto")) publisher.map(String::toUpperCase) .map { value -> if(value == ">") "<" else value } .subscribe { value -> print(value) /* consumer */ } // Imprime: GOKU<NARUTO
  • 53. Reactor val monoPublisher = Mono.just("Goku is the best!") monoPublisher.subscribeOn(Schedulers.parallel()) .subscribe { print("[${Thread.currentThread().name}] $it") } println("[${Thread.currentThread().name}] Who is the best?") // Imprime: [main] Who is the best? // [parallel-1] Goku is the best!
  • 54. Reactor val monoPublisher = Mono.just("Goku is the best!") monoPublisher.subscribeOn(Schedulers.parallel()) .subscribe { print("[${Thread.currentThread().name}] $it") } println("[${Thread.currentThread().name}] Who is the best?") // Imprime: [main] Who is the best? // [parallel-1] Goku is the best!
  • 55. Reactor val monoPublisher = Mono.just("Goku is the best!") monoPublisher.subscribeOn(Schedulers.parallel()) .subscribe { print("[${Thread.currentThread().name}] $it") } println("[${Thread.currentThread().name}] Who is the best?") // Imprime: [main] Who is the best? // [parallel-1] Goku is the best!
  • 56. Reactor val monoPublisher = Mono.just("Goku is the best!") monoPublisher.subscribeOn(Schedulers.parallel()) .subscribe { print("[${Thread.currentThread().name}] $it") } println("[${Thread.currentThread().name}] Who is the best?") // Imprime: [main] Who is the best? // [parallel-1] Goku is the best!
  • 57. Reactor val monoPublisher = Mono.just("Goku is the best!") monoPublisher.subscribeOn(Schedulers.parallel()) .subscribe { print("[${Thread.currentThread().name}] $it") } println("[${Thread.currentThread().name}] Who is the best?") // Imprime: [main] Who is the best? // [parallel-1] Goku is the best!
  • 58. Reactor val monoPublisher = Mono.just("Goku is the best!") monoPublisher.subscribeOn(Schedulers.parallel()) .subscribe { print("[${Thread.currentThread().name}] $it") } println("[${Thread.currentThread().name}] Who is the best?") // Imprime: [main] Who is the best? // [parallel-1] Goku is the best!
  • 59. Arquitetura do Webflux @Controller, @RequestMapping Router functions spring-webflux HTTP / Reactive Streams Tomcat, Jetty, Netty, Undertow spring-webmvc Servlet API Servlet Container
  • 60. Webflux Talk is cheap, show me the code!
  • 70. Non-blocking IO IO Operation Thread Running Kernel Process Thread sendo aproveitada para outros processos
  • 73. Event loop É um design pattern!
  • 79. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 80. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 81. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 82. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 83. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 84. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 85. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 86. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 87. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 88. Event loop class EventLoop(private val eventQueue: BlockingQueue<Runnable>) { init { start() } private fun start() { Thread(Runnable { var task = eventQueue.take() while (true) { task.run() task = eventQueue.take() } }).start() } fun put(task: Runnable) { eventQueue.put(task) } }
  • 89. Event loop E se for necessário conectar com o DB ou ler um arquivo, isso não vai bloquear o Event Loop?
  • 93. Event loop - NIO Libs ● R2DBC - Reactive Relational Database Connectivity ● Web Client ● Reactor Netty (UDP, TCP, HTTP)
  • 94. Event loop E se caso essa rotina for estritamente bloqueante? Por exemplo, uma que use muito CPU Bound. O que deve ser feito?
  • 95. Event loop Event Loop Worker Thread Pool Event Queue Thread
  • 96. Event loop Event Loop Blocking Ops Worker Thread Pool Event Queue Thread
  • 97. Event loop Event Loop Blocking Ops Worker Thread Pool Event Queue Thread put(event)
  • 98. Event Loop - CPU Bound exemplo fun doHeavyProcess() { println("running other spring boot application rs") }
  • 99. Event Loop - CPU Bound exemplo @PostMapping("/heavy-process") fun heavyProcess(): Mono<ResponseEntity<Nothing>> { return Mono .defer { Mono.justOrEmpty(::doHeavyProcess) } .subscribeOn(Schedulers.parallel()) .map { ResponseEntity.ok().build<Nothing>() } }
  • 100. Event Loop - CPU Bound exemplo @PostMapping("/heavy-process") fun heavyProcess(): Mono<ResponseEntity<Nothing>> { return Mono .defer { Mono.justOrEmpty(::doHeavyProcess) } .subscribeOn(Schedulers.parallel()) .map { ResponseEntity.ok().build<Nothing>() } }
  • 101. Event Loop - CPU Bound exemplo @PostMapping("/heavy-process") fun heavyProcess(): Mono<ResponseEntity<Nothing>> { return Mono .defer { Mono.justOrEmpty(::doHeavyProcess) } .subscribeOn(Schedulers.parallel()) .map { ResponseEntity.ok().build<Nothing>() } }
  • 102. Event Loop - CPU Bound exemplo @PostMapping("/heavy-process") fun heavyProcess(): Mono<ResponseEntity<Nothing>> { return Mono .defer { Mono.justOrEmpty(::doHeavyProcess) } .subscribeOn(Schedulers.parallel()) .map { ResponseEntity.ok().build<Nothing>() } }
  • 104. + Utiliza melhor os recursos do hardware + Alta disponibilidade Vantagens
  • 105. - Codebase mais complexo - É mais complexo para debugar - Suposições erradas podem bloquear todo o servidor - Não trabalha com thread local - Logs - Telemetria - Stack Traces podem se tornar inúteis Desvantagens
  • 106. Referências ● https://medium.com/@rarepopa_68087/reactive-programming-with-spring-boot-and-webflux-734086f8c8a5 ● https://tanzu.vmware.com/content/slides/reactive-applications-on-apache-tomcat-and-servlet-3-1-containers ● https://blog.codecentric.de/en/2019/04/explain-non-blocking-i-o-like-im-five/ ● https://www.youtube.com/watch?v=2oXqbLhMS_A ● https://medium.com/ing-blog/how-does-non-blocking-io-work-under-the-hood-6299d2953c74 ● https://www.scnsoft.com/blog/java-reactive-programming ● https://www.slideshare.net/kslisenko/networking-in-java-with-nio-and-netty-76583794 ● https://www.reactivemanifesto.org/glossary#Non-Blocking ● https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html ● https://dzone.com/articles/spring-webflux-eventloop-vs-thread-per-request-mod ● https://www.reactive-streams.org/ ● https://projectreactor.io/docs/core/release/reference/ ● http://tutorials.jenkov.com/netty/overview.html