A Decisão de Escolher o Framework do Momento (ou do Futuro)

Lírio
Devspoint
Published in
7 min readSep 21, 2021

Atualmente estive vivendo o dilema, Spring Native, Quarkus ou Micronaut?

Essa história dentro do Mundo Java é antiga, onde o Java EE dominava o cenário e então Rod Johnson percebeu uma grande dor ao utilizar um Servidor de Aplicação, com o diferencial de injetar os objetos/dependências (DI) para utiliza-los dentro das suas classes com uma única instancia na aplicação utilizando inversão de controle (IoC). No entanto aplicações mais simples poderiam utilizar o velho e bom Tomcat, mas sem o poder da injeção de dependência, então Rod Johnson iniciou um projeto chamado Spring.

Quando @Fabiano Goes me apresentou Spring, (na hora falei “o negócio é Struts2” hahahha), então quando fui testar esse novo framework e percebi que o Spring era diferente e divertido de programar, escolhemos seguir com Spring, e deixar Struts2, JSF e outros frameworks de lado.

No entanto, no mercado, sempre éramos confrontados com a frase “Mas o Spring não segue a especificação da Sun (depois Oracle)”. E a resposta que dávamos sempre era a mesma, “Não segue, mas é bem melhor desenvolver com Spring!!!”

E de repente o mercado virou e todas as empresas estavam mudando para o Spring.

Do mesmo jeito que o Spring nasceu em cima de dores ao desenvolver com Java EE, recentemente outros frameworks nasceram em cima de dores que o Spring não resolve, dois frameworks muitos citados na comunidade Java hoje em dia são Micronaut e Quarkus, e utilizando uma tal de GraalVM.

Mas o por que de tudo isso? E qual o problema do Spring 🤔?

Quarkus

Quarkus é um (não tão) novo framework Java, que nasceu com o objetivo de contrapor aquele velho meme de que Java é lento. Simples e potente as aplicações criadas em Quarkus são preparadas para rodar em ambiente Cloud, cluster Kubernetes ou Serverless, sendo muito mais leve e rápido, no próprio site do Quarkus ele se vende como Java Supersonic/Subatomic.

A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards

E por que Quarkus é mais rápido?

GraalVM

GraalVM é um projeto da Oracle criado com o principal motivo de substituir a JVM e promete diminuir o consumo de memória e trazer mais performance, tanto em tempo de execução ou no boot da aplicação que é executado em 2 dígitos de milissegundos :)

Just-in-Time vs Ahead of Time

O Java utilizava JIT (Just-in-Time) para compilar suas aplicações, onde era gerado os bytecodes e a JVM os interpretava (e compilava) em tempo de execução, então no começo da execução das aplicações Java as primeiras requisições são mais lentas até a máquina esquentar e as próximas requisições terão uma melhor performance.

Já as aplicações Java que utilizando GraalVM utilizam o AoT (Ahead of Time) no build, isolando reflections e antecipando toda a compilação, em tempo de execução NÃO existe reflections sendo executadas.

O Quarkus não nasceu para rodar com GraalVM, nasceu até antes, e no meio do caminho quando surgiu o GraalVM começaram a utiliza-lo.

Micronaut

Lançado em 2018, um ano antes do Quarkus, ambos com a proposta muita semelhante, minimizar o consumo de memória da aplicação, reduzir o tempo de inicialização e de ser Nativo para Nuvem. O Micronaut também oferece suporte a execução nativa com GraalVM.

Container First

Container-First surgiu para que desde o início sua aplicação seja pensada para rodar em container, Container First e Cloud Native estão lado a lado, sua aplicação Spring-Boot criada e desenvolvida seguindo os 12 Factores, como Configuração Centralizada, Codebase, Logs, Escala e etc... Ainda assim pode apresentar alguns problemas, principalmente em sistemas distribuídos, e a escalabilidade horizontal pode ser um problema. Em questões de negócio, se sua aplicação utilizar melhor os recursos computacionais e uma melhor escalabilidade vertical irá utilizar menos uma escala horizontal, ou seja irá economizar $$$, e tecnicamente, consumindo menos memória como mencionado anteriormente, com mais performance, tempo de resposta menor e um boot mais rápido (Se você já fez um teste de uma aplicação Spring-Boot com AWS Lambda sabe o que eu quero dizer, comparado ao Python ou NodeJS nesse ponto Spring+Java fica devendo).

Então, quer dizer que o Spring é lento?

Spring Native (Build e Boot)

Claro que Spring deu uma resposta, e isso foi em Março (de 2021), lançando a versão Experimental do Spring Native utilizando GraalVM.

Criando Projeto Spring Boot Web Imperativo

Java, Maven, Spring Web, H2, Spring Data JPA, Lombok e Spring Native

Na aplicação configurei um schema.sql e data.sql para inserir um registro no banco de dados no Boot. Criei um Controller, Entity e uma Repository, ao subir a aplicação com a JVM o Tempo de inicialização foi de 4.073 seconds.

http://localhost:8080/customers

Gerando o Build com Native Image

Para gerar o build native image em spring-native vamos utilizar o maven e como pré-requisitos precisaremos do GraalVM e o Docker.

→ mvn clean package spring-boot:build-image

Como nada é perfeito, GraalVM também não e tem suas desvantagens, uma delas é o custo do build, o tempo é bem demorado e pode variar bastante, nesse exemplo demorou 15 minutos e 53 segundos, imagine você precisando gerar um hot-fix para corrigir um erro em produção.

[INFO] Successfully built image ‘docker.io/library/spring-web-imperative:0.0.1-SNAPSHOT’[INFO] BUILD SUCCESS
[INFO] Total time: 15:53 min

Ao terminar o processo uma imagem docker da sua aplicação foi gerado, vamos subir e ver o tempo de inicialização.

→ docker run -p8080:8080 docker.io/library/spring-web-imperative:0.0.1-SNAPSHOT

Tempo de inicialização com GraalVM: 0.194 segundos.

Agora vamos criar uma aplicação Spring Boot Webflux Reativo

Kotlin, Gradle, Spring Webflux, H2, Spring Data R2DBC, e Spring Native

Tempo de inicialização com JVM: 3.038 segundos.

Nessa aplicação utilizei reatividade de ponta a ponta, caso queira saber mais de programação reativa e paradigma funcional leia o artigo O que é Programação Reativa e Spring WebFlux?

Vamos gerar o build native como fizemos com o spring-web-imperative só que agora utilizando o Gradle.

./gradlew clean bootBuildImage

Tempo de build foi 9m e 48s

Successfully built image 'docker.io/library/spring-webflux-reactive:0.0.1-SNAPSHOT'BUILD SUCCESSFUL in 9m 48s
10 actionable tasks: 10 executed

docker run -p8080:8080 spring-webflux-reactive:0.0.1-SNAPSHOT

0.084 seconds

Tempo de inicialização com GraalVM: 0.084 segundos.

Ranking por tempo de inicialização

  1. spring-webflux-reactive com GraalVM → 84 milissegundos
  2. spring-web-imperative com GraalVM → 194 milissegundos
  3. spring-webflux-reactive com JVM → 3.038 segundos
  4. spring-web-imperative com JVM → 4.073 seconds

Conclusão

No meu Tech Radar sigo empolgado com Quarkus e o outro pé mantendo no Spring e em terceiro e sigo somente observando o Micronaut.

Se chegar a 1% das aplicações de mercado precisarem se preocupar com um tópico como esse, é muito!!! O velho e bom Spring-Boot Web imperativo com JVM já resolve a maioria dos problemas das aplicações de mercado, se você precisa que o start da sua aplicação seja rápido, vale a pena estudar o GraalVM, JVM ainda acaba entregando mais quando se trata de throughput!

Recentemente li o livro 14 Hábitos de Desenvolvedores Altamente Produtivos e logo no inicio do livro o autor provoca uma reflexão, FOMO (Fear Of Missing Out), ou medo de estar perdendo algo. E se estivermos perdendo nosso tempo com o framework que escolhemos e não será ele que irá permanecer no futuro? O fato é, não existe a melhor ferramenta para tudo, então devemos praticar o JOMO (Joy Of Missing Out) ou a alegria de estar perdendo algo :), Seja Feliz com o que voce sabe!!!

Fundamentos sempre será mais importante do que aprender um novo framework.

E aí? Qual o seu framework?

Github: spring-web-imperative e spring-webflux-reactive

Ref.:

--

--