Spring Native implementa 0.059s Inicie um projeto SpringBoot!

prefácio

Recentemente, usei o Spring Cloud Alibaba para criar um projeto de arquitetura de microsserviços e encontrei um problema durante a implantação: memória insuficiente. No momento, o projeto tem 7 microsserviços, porque eu só tenho um servidor Alibaba Cloud (2C 4G), então só posso implantar todos os microsserviços em um servidor, e o método de implantação é usar o docker para criar uma imagem jar gorda de springboot, cada microsserviço ocupa cerca de 500M de memória sem adicionar nenhum parâmetro de ajuste da JVM.

Por ser um microsserviço, deve ser implantado: nacos, além de redis, sentinela, rocketmq, elk, etc. (da Alibaba Cloud comprada pela mysql), só rodar esses aplicativos ocupa mais de 2G de memória, e o restante Após a implantação de 4 microsserviços, a memória de mais de 1 G abaixo está cheia, então é iniciada a otimização inicial da memória do aplicativo springboot:

Adicione parâmetros JVM para otimizar o tamanho da memória

# JVM初始分配的内存由-Xms指定,默认是物理内存的1/64
-Xms128m
# JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4
-Xmx128m
# 规定了每个线程虚拟机栈及堆栈的大小,一般情况下,256k是足够的,此配置将会影响此进程中并发线程数的大小。
-Xss256k
# 指定并行GC线程的数量,一般最好和CPU核心数量相当
-XX:ParallelGCThreads=2

Por padrão, quando a memória heap livre for menor que 40%, a JVM aumentará o heap até o limite máximo de -Xmx; quando a memória heap livre for maior que 70%, a JVM reduzirá o heap até o limite mínimo de -Xms.

Portanto, o servidor geralmente configura -Xms e -Xmx iguais para evitar o ajuste do tamanho do heap após cada GC. A memória heap dos objetos é recuperada por um sistema automático de gerenciamento de memória chamado coletor de lixo.

Por padrão, quando o número de CPUs é menor que 8, o valor de ParallelGCThreads é igual ao número de CPUs. Meu servidor é 2C, então este parâmetro pode ser omitido. Depois de concluída a configuração, inicie o serviço e verifique se a memória realmente ficou menor, dos 500M originais para 100~200M, mas não é o efeito que desejo. O efeito que espero é atingir o nível de dezenas de M .

Depois de consultar muitas informações na Internet, aprendi que posso usar a nova tecnologia do Spring Native para atender às minhas necessidades. (Esta tecnologia está em fase de rápida iteração, com grandes mudanças, é recomendada para aprendizado pessoal, não para produção)

Após o projeto SpringBoot usar o Spring Native:

  1. A velocidade de inicialização do aplicativo é extremamente rápida, no nível de milissegundos
  2. Menor consumo de memória em tempo de execução, o tamanho oficial da imagem do Spring Boot, Spring MVC, Jackson, Tomcat é de 50M
  3. Para conseguir o efeito anterior, o custo é que o tempo de compilação é maior (mesmo uma compilação do Hello Word leva 2 minutos, mas depende principalmente da configuração do computador, a minha é de cerca de 2min)

O que é Spring Native

Resumindo, é melhorar a competitividade do Java na nuvem nativa (entendimento pessoal).

O trecho a seguir foi extraído do leia-me do Spring Native no GitHub:

O Spring Native fornece suporte beta para compilar aplicativos Spring em executáveis ​​nativos usando o compilador de imagem nativo GraalVM
para fornecer opções de implantação nativa normalmente projetadas para serem empacotadas em contêineres leves. Na verdade, o objetivo é oferecer suporte a aplicativos Spring Boot quase não modificados nesta nova plataforma.

O seguinte é extraído de outros blogs:

Nos últimos anos, a palavra "nativo" foi inundada em computação em nuvem, computação de borda e outros campos, e os idiomas nativos preferidos sempre foram Golang, Rust e outros idiomas de desenvolvimento que fogem do Sandbox. Java se beneficiou do conceito de compilação e execução únicas em todos os lugares que era popular no século passado e tem sido popular até agora. No entanto, por esse motivo, os programas Java não podem ser separados do ambiente operacional JVM, tornando-os menos popular com programas nativos. Na atual enxurrada de nuvem nativa, a inchada JVM faz com que os aplicativos Java pareçam incomparavelmente maiores do que outras linguagens, e vários mestres também pensaram em muitas maneiras de tornar o Java mais "nativo".

insira a descrição da imagem aqui

combate

As informações ambientais relacionadas a este combate real são as seguintes:

  • SO: Windows10 21H1
  • IDE: IntelliJ IDEA 2021.2.3
  • JDK:graalvm-ce-java11-21.3.0
  • Especialista: 3.6.3
  • Docker Desktop para Windows: 20.10.12
  • Bota de mola: 2.6.2
  • Spring Native: 0.11.1
    insira a descrição da imagem aquiaprendido com o documento oficial (acima)

Os aplicativos que usam Spring Native devem ser compilados com Java 11 ou Java 17.

Existem duas abordagens principais para criar aplicativos nativos do Spring Boot:

  1. Use o suporte do Spring Boot Buildpacks para gerar contêineres leves contendo executáveis ​​nativos.
  2. O uso do plug-in Maven de imagem nativa GraalVM oferece suporte à geração de executáveis ​​nativos.

Após várias armadilhas, o método 1 e o método 2 foram usados ​​com sucesso nesta máquina. simplesmente coloque:

O método 1 é posterior ao SpringBoot2.3, você pode usar o plug-in spring-boot-maven-plugin para criar a imagem do docker, use o comando mvn spring-boot:build-image combinado com a API do Docker para realizar a construção do Aplicativo nativo Spring Boot e execute-o com sucesso Depois disso, uma imagem do docker será gerada diretamente e, em seguida, execute esta imagem. Não precisamos escrever o Dockerfile novamente. As configurações de parâmetros relevantes são todas definidas em pom.xml (sob o tag de configuração do plug-in e o docker-maven do fabric8 ou spotify -plugin é muito semelhante).

O método 2 não requer a instalação do docker, mas a instalação do Visual Studio e, em seguida, a execução do comando mvn -Pnative package gerará um arquivo executável (.exe), basta executá-lo.

As principais diferenças são as seguintes

1 O ambiente depende de diferentes

  • O método 1 precisa instalar o Docker
  • O método 2 precisa instalar o Visual Studio (requer alguns componentes individuais: 2 MSVC, 1 Windows 10 SDK)

2 Os comandos maven executados são diferentes

  • O método 1 é mvn spring-boot:build-image
  • O método 2 é mvn -Pnative package

Como cada microsserviço usa a implantação do Docker em vez de arquivos exe, o método 1 apenas atende às minhas necessidades, portanto, usarei Spring Boot Buildpacks para criar aplicativos nativos Spring Boot posteriormente.

Instale Graal VM (graalvm-ce-java11-windows-amd64)

Endereço oficial de download:

https://www.graalvm.org/downloads/
insira a descrição da imagem aquiinsira a descrição da imagem aqui

Configurar variáveis ​​de ambiente

insira a descrição da imagem aquiinsira a descrição da imagem aquiPara o método 1, as três imagens acima parecem precisar apenas configurar JAVA_HOME. Se você quiser ter sucesso uma vez, é recomendável configurar todas as três e você mesmo pode testar mais tarde.

Verifique se a instalação foi bem-sucedida
insira a descrição da imagem aqui

Instalar imagem nativa

Abra um novo cmd, digite o seguinte comando e aguarde a instalação

gu install native-image

Não consegui executar esta etapa. A solução é baixar manualmente a imagem nativa do github, descompactá-la e instalá-la

https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/native-image-installable-svm-java11-windows-amd64-21.3.0.jar

O jar também pode ser descompactado com o WinRAR. Após a descompactação, é o seguinte

insira a descrição da imagem aqui
Abra cmd no diretório bin, digite o seguinte comando e aguarde a instalação

$ gu install -L native-image*

Instalar área de trabalho para Windows

As etapas específicas são omitidas, basta seguir a documentação oficial:

https://docs.docker.com/desktop/windows/install/

Configurar pom.xml

A frente é todo trabalho preparatório, esta etapa é a chave

Primeiro, crie rapidamente um projeto Spring Boot, chamei-o de spring-native

O pom completo é o seguinte

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>ltd.pcdd</groupId>
    <artifactId>spring-native</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-native</name>
    <description>spring-native</description>
    <properties>
        <java.version>11</java.version>
        <repackage.classifier/>
        <spring-native.version>0.11.1</spring-native.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.experimental</groupId>
            <artifactId>spring-native</artifactId>
            <version>${spring-native.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.experimental</groupId>
                <artifactId>spring-aot-maven-plugin</artifactId>
                <version>0.11.1</version>
                <executions>
                    <execution>
                        <id>generate</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!--Spring Boot 2.3发布后带来了新特性之一就是对构建镜像的便捷支持-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <image>
                        <builder>paketobuildpacks/builder:tiny</builder>
                        <env>
                            <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
                        </env>
                    </image>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-release</id>
            <name>Spring release</name>
            <url>https://repo.spring.io/release</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-release</id>
            <name>Spring release</name>
            <url>https://repo.spring.io/release</url>
        </pluginRepository>
    </pluginRepositories>

</project>

Este artigo apresenta a versão Spring Native0.11.1 e sua versão Spring Boot correspondente deve ser 2.6.2. O exemplo acima é apenas um exemplo de configuração básica. No desenvolvimento real, ele precisa ser configurado sob a tag de configuração do spring-boot- plug-in maven-plugin Muitos outros parâmetros.

Por exemplo, endereço remoto do docker e caminho do certificado, parâmetros de ajuste do jvm, especificação do arquivo de configuração, nome da imagem do docker, endereço do armazém da porta, etc. A melhor maneira é ler a documentação oficial do spring-boot-maven-plugin, aqui para configurar os parâmetros do jvm como um exemplo

insira a descrição da imagem aquiDe acordo com a documentação oficial, você só precisa configurá-lo na tag de configuração, por exemplo

<image>
 <builder>paketobuildpacks/builder:tiny</builder>
 <env>
  <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
  <BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"> </BPE_DELIM_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xms128m</BPE_APPEND_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xmx128m</BPE_APPEND_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xss256k</BPE_APPEND_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:ParallelGCThreads=2</BPE_APPEND_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:+PrintGCDetails</BPE_APPEND_JAVA_TOOL_OPTIONS>
 </env>
</image>

Existem muitos outros parâmetros de configuração.

Documentação oficial:

https://docs.spring.io/spring-boot/docs/2.6.2/maven-plugin/reference/htmlsingle/#build-image

Execute o comando maven

mvn clean
mvn '-Dmaven.test.skip=true' spring-boot:build-image

Depois de baixar as dependências relevantes, o ventilador do computador começou a zumbir.Verificar o gerenciador de tarefas descobriu que a utilização da CPU era de 100% e o uso da memória disparou e, finalmente, estabilizou em 90%+.

construir com sucesso
insira a descrição da imagem aqui

Criar e executar o contêiner

Ver todos os espelhos
insira a descrição da imagem aquispring-native é o espelho construído

Crie e execute o contêiner
insira a descrição da imagem aquiVerifique os logs no Docker Desktop e descubra se o aplicativo é iniciado com êxito e leva apenas um tempo para iniciar. , que é de 59 ms, realmente confirma a sentença de que o Spring Native começa no nível de milissegundos.
insira a descrição da imagem aquiChame a interface com sucesso

insira a descrição da imagem aqui
Verifique a memória ocupada no Docker Desktop, apenas cerca de 28M.

insira a descrição da imagem aqui
insira a descrição da imagem aquiLeva 3 segundos para iniciar o aplicativo sem usar o Spring Native e o uso de memória chega a 511M.

O artigo é apenas para referência e é recomendado estudar em conjunto com a documentação oficial mais recente do Spring Native.

https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/index.html

Acho que você gosta

Origin blog.csdn.net/weixin_43114209/article/details/131533600
Recomendado
Clasificación