Quarkus - Um novo olhar sobre o Java nativo da nuvem

Olá Habr!

No próximo ano, planejamos desenvolver seriamente temas de contêiner, Java nativo da nuvem e Kubernetes . Uma continuação lógica desses tópicos em russo será a história sobre a estrutura do Quarkus , já considerada em um bom artigo sobre Habré. O artigo de hoje não se concentra tanto no “dispositivo Java ultra- rápido subatômico ” como nas perspectivas que o Quarkus traz para a Enterprise.

Java e a JVM ainda são extremamente populares, mas, ao trabalhar com tecnologias sem servidor e microsserviços orientados à nuvem, Java e outras linguagens para a JVM são usadas cada vez menos, pois ocupam muito espaço na memória e carregam muito lentamente, o que as torna inadequadas para use com recipientes de vida curta. Felizmente, esta situação está começando a mudar graças ao Quarkus.

1. Introdução


Quanto mais eu desenvolvo DevOps, contêineres e tecnologias sem servidor, mais descobri que estou escrevendo meu código em contêiner em contêineres leves ou FaaS em Python ou JavaScript. Java é simplesmente muito pesado para inicializar para usar em uma estrutura sem servidor. Em relação aos microsserviços, JavaScript ou Python fornecem carregamento mais rápido e contêineres mais compactos, tornando o Java mais eficiente.



Python e JavaScript são os melhores idiomas para criar microsserviços baseados em nuvem

Java tem mais de 20 anos e, no momento de sua criação, o mundo era completamente diferente do que é agora. Com o advento da JVM, grandes problemas foram resolvidos - conseguimos escrever o código uma vez e executá-lo em várias plataformas e sistemas operacionais. Os contêineres permitem empacotar aplicativos, bibliotecas e recursos do sistema operacional em contêineres separados, e cada um desses contêineres pode funcionar em qualquer lugar. A portabilidade que a JVM fornece agora é menos relevante . Ao mesmo tempo, estávamos prontos para incorrer em custos adicionais para garantir a portabilidade, mas agora esses tempos já passaram. Agora você precisa de um trabalho rápido, com atrasos mínimos e aplicativos reativos que sempre estarão disponíveis . Contêineres e ferramentas de orquestração de contêineres, como o Kubernetes, fornecem esses recursos, independentemente da linguagem de programação.

As empresas que mudam para arquiteturas de microsserviço pegam seus serviços baseados em Spring escritos em Java, os vinculam a arquivos jar pesados, adicionam JDKs e os executam em um contêiner baseado em Linux. Essa solução funciona, mas você precisa lidar com contêineres pesados ​​de 500 MB de tamanho, que são colocados em um estado de acessibilidade por 10 a 30 segundos cada; Este é um problema sério. Após a migração, muitas empresas estão migrando lentamente para o Python, deixando os serviços do lado do servidor em Java e, no final, parando no FaaS.

Hoje, as tecnologias sem servidor e o FaaS são muito populares porque permitem que você se concentre nas funções de escrita sem se preocupar com a infraestrutura. Seja como for, todos eles funcionam em contêineres, mas o provedor de nuvem gerencia seu ciclo de vida. A melhor parte é que, depois de um certo tempo, o provedor para completamente o contêiner e retoma seu trabalho somente após a próxima chamada, ou seja, você paga apenas pelo tempo de trabalho real. A primeira chamada de função pode durar um pouco mais que o normal, este é o famoso início a frio . O fato é que o contêiner precisa de carregamento primário. Usar Python ou JavaScript não é um problema tão grande, mas no caso de Java, o carregamento inicial pode levar de 10 a 15 segundos, e essa é uma frase e uma das razões para o declínio na popularidade do Java. Agora precisamos de um código que possa iniciar, concluir a tarefa e depois parar . Não queremos lidar com muitos threads ou processos de execução demorada, precisamos de processos de vida curta que possam carregar muito rapidamente .

Apresentando o Quarkus


Se você lê blogs técnicos ou acompanha as notícias, provavelmente pensa que o paradigma sem servidor está dominando o mundo, e todos o encaram com extremo entusiasmo. Agora, uma startup pode escrever funções e fornecê-las na nuvem como um serviço - graças ao uso de JavaScript - e também escalá-las para oferecer suporte a milhões de usuários, sem precisar gerenciar a infraestrutura. É verdade que também existe um mundo real fora do Vale do Silício: instituições financeiras, governo, varejo e muitas outras indústrias atendidas com milhões de linhas Java, caras demais para serem reescritas. Portanto, devemos tomar como certo o fato de que nessas indústrias resta continuar a usar contêineres pesados.



Hoje , o GraalVM e, em particular, o Substrate VM, abrem as portas para o futuro glorioso e de longo prazo da linguagem Java. GraalVM é uma máquina virtual universal para executar aplicativos escritos em JavaScript, Python, Ruby, R e linguagens para a JVM, em particular Java, Scala ou Kotlin. O mais interessante é que o GraalVM permite pré-compilar (no modo AOT) os programas em um arquivo executável nativo . Isso significa que você pode compilar seu código Java diretamente no código específico da máquina. O programa resultante não funciona na Java HotSpot VM, mas usa todos os componentes necessários, em particular gerenciamento de memória, agendamento de encadeamentos de outra implementação de uma máquina virtual chamada Substrate VM. A VM do substrato é gravada em Java e seu código é compilado em um executável nativo. O programa resultante é iniciado mais rapidamente e, consequentemente, fornece menor sobrecarga no uso de memória em comparação com o Java VM. Isso é ótimo, mas você provavelmente pensa: compilação antecipada? Isso contradiz a idéia básica para a qual a JVM foi criada, ou seja, o uso de código escrito uma vez em todos os lugares! Isso é loucura !!! No entanto, pense por si mesmo: agora temos contêineres e eles não precisam de uma JVM. Os aplicativos de contêiner convencionais criados usando a inicialização Spring têm um nível extra de abstração, o que é absolutamente desnecessário no mundo em que o Kubernetes está . Você tem um aplicativo Java em execução na JVM dentro do contêiner, esse contêiner permanece inalterado, porque hoje o produto final é um contêiner, não um aplicativo. Agora estamos empacotando contêineres, não arquivos WAR. Portanto, todos os custos associados ao uso do aplicativo JVM dentro do contêiner se tornam inúteis , e o AOT se torna uma decisão muito lógica se você for empacotar seus aplicativos em contêineres.

É verdade que a compilação AOT limita seriamente os recursos dinâmicos do Java (carregar classes em tempo de execução, reflexão, proxies etc.). Na prática, isso significa que 90% do ecossistema Java não funcionará sem mudanças. Consequentemente, o ecossistema Java deve se adaptar . Há boas notícias: a maior parte disso pode ser feita durante a montagem!

Este é o poder do Quarkus. Ele usa o GraalVM e fornece um ecossistema que suporta a compilação AOT no momento da construção; portanto, usando Java, você pode criar binários nativos. Graças ao Quarkus, o GraalVM é disponibilizado para desenvolvedores Java .

Introdução ao Quarkus


Como explicado acima, o Quarkus fornece compilação antecipada para aplicativos Java, e isso produz um ecossistema de Java subatômico supersônico; O Quarkus é caracterizado por carregamento ultra-rápido - e o Java retorna ao jogo no campo do desenvolvimento baseado em nuvem. Durante anos, nenhuma nova tecnologia me inspirou - e não estou sozinha nisso .

Leia o guia para iniciantes - e veja por si mesmo. Ainda existem muitas empresas usando Java + JPA dentro do contêiner, mas nessa configuração, o carregamento pode levar 15 segundos e, no caso do Quarkus, 0,005!



Estatísticas do Quarkus

Você está usando o mesmo IDE e as mesmas ferramentas com as quais está acostumado no mundo do Spring Boot. Para criar seu projeto, use Maven ou Gradle. O projeto pode ser executado diretamente no IDE e, além disso, uma reinicialização em tempo real está disponível para você com todas as alterações e você não precisa reiniciar o aplicativo. O Quarkus não é o Spring, portanto, se você usa o Spring Boot, precisará migrar o código específico do Spring. Felizmente, o Quarkus fornece um nível de compatibilidade para a implementação de dependências do Spring , o que simplifica bastante o trabalho. A estrutura do Quarkus é compatível com os padrões, o que significa facilidade de portabilidade e suporte para seu código.

Processo de Desenvolvimento Quarkus


O Quarkus pode ser usado no modo de desenvolvimento, lembrando o Spring Boot. Com ele, você também pode embalar seu projeto em jarra grossa. Isso é muito conveniente para testar e depurar seu código, pois a reinicialização ao vivo é suportada; mas você precisa compilar com antecedência para entrar em produção. Todo o processo é mostrado no diagrama a seguir:



  • Primeiro, crie o aplicativo no seu IDE favorito e, em seguida, execute-o no modo de desenvolvedor com: “ mvnw compile quarkus:dev ”, como faria com o aplicativo Spring Boot. Você também pode embalá-lo em uma jarra grossa.
  • Assim que você concluir a etapa anterior e o resultado lhe mvnw package -Pnative - você está pronto para criar o arquivo binário Java, basta executar: “ mvnw package -Pnative ”. Isso levará algum tempo, pois o código nativo será gerado durante a compilação com antecedência! Quando esta etapa estiver concluída, você terá à sua disposição um arquivo executável ultra-pequeno e ultra-rápido, mas ele só funcionará na sua plataforma / sistema operacional, ou seja, não será portado! Mas isso é normal, pois podemos colocá-lo em um contêiner - e assim garantir a portabilidade. Aqui está como fazer isso: ./mvnw package -Pnative -Dnative-image.docker-build=true 4 - e removemos o executável do contêiner do Docker, ou seja, executamos a montagem nativa dentro do contêiner e criamos um arquivo binário. Essa técnica pode não funcionar no seu laptop se o sistema operacional for diferente da plataforma de destino especificada no DockerFile gerado pelo Quarkus durante a criação do projeto.
  • Depois de ter o binário, basta criar uma imagem com base no arquivo docker. docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart .
  • Por fim, o aplicativo pode ser iniciado no Docker ou no Kubernetes: docker run -i --rm -p 8080:8080 quarkus-quickstart/quickstart

Recursos do Quarkus


O Quarkus possui muito mais recursos do que o código Java nativo.

  • Unificação de recursos imperativos e reativos: permite combinar código imperativo familiar com código não-bloqueador, escrito em um estilo reativo.
  • O desenvolvedor está satisfeito : uma configuração unificada, configuração Zero, reinicialização em tempo real, código otimizado otimizado para 80% dos casos comuns e código flexível para os 20% restantes, geração de arquivos executáveis ​​nativos sem problemas, codificação ao vivo.
  • Carregamento incrivelmente rápido, uma área de memória residente incrivelmente pequena (sim, não é apenas do tamanho de um monte!), Que fornece escala vertical quase instantânea e uso de memória muito denso ao orquestrar contêineres em plataformas como o Kubernetes. Veja mais detalhes .
  • O Quarkus oferece uma estrutura holística e fácil de usar, com bibliotecas de primeira classe que você conhece e adora incorporadas nas estruturas de suporte. Mais detalhes .
  • As bibliotecas Hibernate, JPA, REST, JWT etc. são suportadas.
  • Configurações suportadas implantadas no Kubernetes e OpenShift
  • Rastreio aberto usando Jaeger
  • Suporte Kotlin
  • Mensagens com Kafka, Camel ...
  • E muito mais, confira a lista de extensões !

Ecossistema Quarkus


Em resumo, agora você pode executar os serviços transacionais tradicionais JPA / JTA em contêineres super rápidos - tanto na nuvem quanto no local .

Exemplo Quarkus


Nesta seção, vamos dar uma olhada simplificada no guia do iniciante para dar uma impressão do poder do Quarkus.



A maneira mais fácil de criar um novo projeto do Quarkus é abrir uma janela do prompt de comando e executar o seguinte comando:

 mvn io.quarkus:quarkus-maven-plugin:0.12.0:create \ -DprojectGroupId=org.acme \ -DprojectArtifactId=getting-started \ -DclassName="org.acme.quickstart.GreetingResource" \ -Dpath="/hello" 

Isso gera um projeto Maven com o GreetingResuce, fornecendo o endpoint / hello. Também são geradas imagens de janela de encaixe Dockerfile para arquivos nativos e jvm (imagens tradicionais na forma de jar grosso). O código é muito limpo e simples:

 @Path("/hello") public class GreetingResource { @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "hello"; } } 

Para executar o aplicativo, use: ./mvnw compile quarkus:dev
O aplicativo é empacotado usando o pacote ./mvnw. O resultado são 2 arquivos jar:

  • Getting-Start-1.0-SNAPSHOT.jar - contém apenas classes e recursos do projeto. Este é um artefato comum resultante da montagem do Maven;
  • Getting-Start-1.0-SNAPSHOT-runner.jar é um jar executável. Note que isto não é "uber-jar", existem dependências aqui, elas são copiadas para o diretório target / lib.

Você pode iniciar o aplicativo usando: java -jar target / Getting-Start-1.0-SNAPSHOT-runner.jar

Então você precisa baixar e instalar o GraalVM e configurar a variável de ambiente GRAALVM_HOME .

Agora você pode criar um executável nativo com: ./mvnw package -Pnative -Dnative-image.docker-build=true .

Veja como criar uma imagem do Docker: docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart .

Agora ele pode ser iniciado usando qualquer mecanismo de orquestração de contêiner, se você usar o minishift :

 kubectl run quarkus-quickstart --image=quarkus-quickstart/quickstart:latest --port=8080 --image-pull-policy=IfNotPresent 

 kubectl expose deployment quarkus-quickstart --type=NodePort 

Isso é tudo! Agora você tem um contêiner com um serviço Java REST que inicia em 0.004 segundos!

Conclusão


Agora entendo por que estou tão impressionado com a estrutura do Quarkus suportada pela Red Hat. Eu realmente acredito que isso mudará o cenário tecnológico de Java e proporcionará às grandes empresas tradicionais uma oportunidade real de migrar para a nuvem.

O Kubernetes + Knative + Quarkus altera as regras do jogo em um desenvolvimento orientado à nuvem e agradará qualquer desenvolvedor Java.

Este repositório tem muitos exemplos interessantes!

Source: https://habr.com/ru/post/pt482968/


All Articles