O que é Programação Reativa e Spring WebFlux?
Afinal, o que são esses conceitos e tecnologias que vêm chegando cada vez mais forte!? Vou compartilhar um pouco a minha visão sobre o assunto, dando uma leve introdução, começando com:
Processos Bloqueantes e Não Bloqueantes
Mas por que começar com esse assunto? A programação reativa é baseada em código Não Bloqueante, então é essencial entender o termo.
Em aplicações Java é muito comum ver código no estilo imperativo:
Este código é responsável por encontrar o cliente e o pedido no Banco de Dados e após isso atualizar os pontos desse cliente e enviar um email para ele confirmando que recebemos o pedido.
Notem que o código acima está estruturado de forma Bloqueante, ou seja, para a linha 10 ser executada, a linha 9 precisa ter terminado seu processamento, embora não precisemos esperar a atualização de pontos para enviar o email, categorizando nosso código como Código Bloqueante (Blocking Code).
Agora, vamos dar uma olhada no seguinte exemplo:
Com a utilização do CompletableFuture, nós pedimos para o Java que isolasse o processamento do código na linha 9 (enviar email para o cliente) em uma outra Thread, enquanto a Thread principal poderia seguir seu fluxo sem ter que aguardar que o processamento do envio de email tivesse sido finalizado. Esse é um exemplo, embora parcial, de Código Não Bloqueante (Non Blocking Code).
Pronto, com esses termos mais claros, vamos entrar um pouco no assunto da Programação Reativa e entender melhor porque processos Não Bloqueantes são importantes.
Programação Reativa
Um dos pilares da Programação Reativa consiste em uma forma diferente de abordar a utilização da CPU disponível para a aplicação. Geralmente, as aplicações em Java com Tomcat podem abrir, digamos 200 Threads, o que significa que conseguimos receber até 200 requisições simultâneas nessa instância da aplicação. E agora, vamos pensar que a nossa aplicação precisa acessar um Banco de Dados para recuperar informações; Quando isso ocorre, a Thread que é responsável por essa operação de I/O (input/output) fica bloqueada aguardando a resposta do Banco de Dados, o que causa um desperdício de CPU já que ela está esperando a resposta para poder continuar seu processamento.
Ah, e por curiosidade, o que aconteceria com a 201º requisição simultânea? Isso depende do servidor utilizado, no caso do Tomcat ele pode armazenar a requisição para ser processada até um número pré-definido, e caso esse número também exceda, podemos ter erros de Connection Refused.
Na Programação Reativa, através de técnicas como o Event Loop utilizado também na arquitetura do Node.js, conseguimos maximizar a utilização da CPU pois as operações não são bloqueantes.
Diferente do caso onde tínhamos 200 Threads, agora passamos a ter um número muito menor, usualmente proporcional à quantidade de CPU da máquina. Para este exemplo, vou assumir que temos 4 Threads principais, uma quantidade muito inferior quando comparado ao contexto não reativo. Seguindo o cenário descrito acima, a aplicação reativa consegue lidar com muito mais do que 200 requisições simultâneas pois as Threads nunca ficam bloqueadas esperando por alguma resposta de I/O, mesmo possuindo um número menor de Threads.
Toda vez que é necessário realizar uma chamada de I/O, enviamos um “callback” (Método com código a ser executado) que será chamado (call) quando recebermos a resposta da chamada de I/O (back).
Conseguimos assim tirar maior proveito da CPU, que quase sempre estará processando ao invés de ficar em um estado bloqueado. E por que isso é importante? Porque a aplicação conseguirá suportar cargas muito maiores de requisições, conseguindo escalar e ter uma melhor tolerância a falhas. Em suma, aplicações reativas são mais eficientes (e não necessariamente mais performáticas!).
Spring WebFlux
É um módulo do Spring que permite utilizarmos o conceito da Programação Reativa misturado com o Estilo da Programação Funcional + as facilidades que o Spring costuma nos oferecer. Existem diferentes formas de se utilizar a Programação Reativa no Java, e neste artigo vou seguir com exemplo utilizando o WebFlux. O WebFlux abstrai uma das implementação reativas existentes pro Java, o Project Reactor.
Vamos dar uma olhada como ficaria nosso código utilizando o WebFlux:
Sim, o código fica mais complexo! É muito importante ter isso em mente ao decidir optar por esse novo paradigma. Claro, existem outras formas de fazer o exemplo acima, mas queria mostrar que não é tão simples assim. Neste artigo não vou entrar nos detalhes de como o código acima funciona, mas se tiverem interessem, comentem, que eu escrevo mais sobre o assunto.
Conclusão
Eu não vou mentir e falar que é algo fácil de se entender, leva tempo e prática. E também, Programação Reativa não é uma bala de prata, existem diversos pontos a serem considerados, como a complexidade do código, a dificuldade para realizar o debug e o seu caso de uso (entre outros). Se você tiver um cenário onde precisa realizar várias chamadas bloqueantes, talvez não seja o melhor caso para utilizar um modelo reativo.
Espero que eu tenha ajudado vocês a entenderem um pouco mais sobre o assunto! Qualquer dúvida, crítica, sugestão, fiquem à vontade para comentar :)