Eu tenho um aplicativo Spring Boot. Eu adicionei muitas dependências (infelizmente, parece que preciso de todas elas) e o tempo de inicialização aumentou bastante. Basta fazer isso SpringApplication.run(source, args)
leva 10 segundos.
Embora isso possa não ser muito comparado ao que estamos "acostumados", estou infeliz que demore tanto, principalmente porque quebra o fluxo de desenvolvimento. O aplicativo em si é bastante pequeno neste ponto, então presumo que a maior parte do tempo esteja relacionado às dependências adicionadas, não às próprias classes do aplicativo.
Presumo que o problema seja a digitalização do classpath, mas não tenho certeza de como:
- Confirme se é o problema (ou seja, como "depurar" o Spring Boot)
- Se for realmente a causa, como posso limitá-la para que fique mais rápida? Por exemplo, se eu souber que alguma dependência ou pacote não contém nada que o Spring deva verificar, há uma maneira de limitar isso?
Presumo que aprimorar o Spring para ter inicialização de bean paralelo durante a inicialização aceleraria as coisas, mas essa solicitação de aprimoramento está aberta desde 2011, sem nenhum progresso. Vejo alguns outros esforços no próprio Spring Boot, como as melhorias de velocidade do Investigue Tomcat JarScanning , mas isso é específico do Tomcat e foi abandonado.
Este artigo:
embora voltado para testes de integração, sugere o uso lazy-init=true
, porém não sei como aplicar isso a todos os beans do Spring Boot usando a configuração Java - alguma indicação aqui?
Quaisquer (outras) sugestões serão bem-vindas.
fonte
@ComponentScan
eles também serão verificados. Outra coisa é certificar-se de que você não habilitou o registro de depuração ou rastreamento, pois geralmente o registro é lento, muito lento.Respostas:
O Spring Boot faz várias configurações automáticas que podem não ser necessárias. Portanto, você pode querer restringir apenas a configuração automática necessária para o seu aplicativo. Para ver a lista completa de autoconfiguração incluída, apenas execute o log de
org.springframework.boot.autoconfigure
no modo DEBUG (logging.level.org.springframework.boot.autoconfigure=DEBUG
emapplication.properties
). Outra opção é executar o aplicativo Spring Boot com a--debug
opção:java -jar myproject-0.0.1-SNAPSHOT.jar --debug
Haveria algo assim na saída:
Inspecione esta lista e inclua apenas as configurações automáticas de que você precisa:
O código foi copiado desta postagem do blog .
fonte
A resposta mais votada até agora não está errada, mas não vai com a profundidade que gosto de ver e não fornece nenhuma evidência científica. A equipe do Spring Boot fez um exercício para reduzir o tempo de inicialização do Boot 2.0, e o tíquete 11226 contém muitas informações úteis. Também há um tíquete 7939 aberto para adicionar informações de tempo para avaliação de condição, mas não parece ter um ETA específico.
A abordagem mais útil e metódica para depurar a inicialização do Boot foi feita por Dave Syer. https://github.com/dsyer/spring-boot-startup-bench
Eu também tinha um caso de uso semelhante, então peguei a abordagem de Dave de micro-benchmarking com JMH e executei-a. O resultado é o projeto boot-benchmark . Eu o projetei de forma que possa ser usado para medir o tempo de inicialização de qualquer aplicativo Spring Boot, usando o jar executável produzido pela tarefa Gradle
bootJar
(anteriormente chamadabootRepackage
de Boot 1.5). Sinta-se à vontade para usá-lo e fornecer feedback.Minhas descobertas são as seguintes:
-XX:TieredStopAtLevel=1
provavelmente retardaria sua primeira solicitação.fonte
minimal
ou o jar pode simplesmente ser fornecido? Tentei fazer o primeiro, mas não fui muito longe.-Xverify:none
em produção, pois isso quebra a verificação de código e você pode ter problemas.-XX:TieredStopAtLevel=1
está OK se você executar um aplicativo por um período curto (alguns segundos), caso contrário, será menos produtivo, pois fornecerá otimizações de longa execução à JVM.Use of -Xverify:none is unsupported.
o que isso significa?Spring Boot 2.2.M1 adicionou um recurso para suportar a inicialização lenta no Spring Boot.
Por padrão, quando um contexto de aplicativo está sendo atualizado, cada bean no contexto é criado e suas dependências são injetadas. Por outro lado, quando uma definição de bean é configurada para ser inicializada lentamente, ela não será criada e suas dependências não serão injetadas até que sejam necessárias.
Ativando a inicialização lenta definida
spring.main.lazy-initialization
como verdadeiraQuando ativar a inicialização lenta
a inicialização lenta pode oferecer melhorias significativas no tempo de inicialização, mas existem algumas desvantagens notáveis e é importante habilitá-la com cuidado
Para mais detalhes, consulte o Doc
fonte
Conforme descrito nesta pergunta / resposta, acho que a melhor abordagem é, em vez de adicionar apenas aqueles que você acha que precisa, excluir as dependências que você sabe que não precisa.
Veja: Minimize o tempo de inicialização do Spring Boot
Em suma:
Você pode ver o que está acontecendo nos bastidores e habilitar o registro de depuração tão simples quanto especificar --debug ao iniciar o aplicativo a partir da linha de comando. Você também pode especificar debug = true em seu application.properties.
Além disso, você pode definir o nível de registro em application.properties tão simples como:
logging.level.org.springframework.web: DEBUG logging.level.org.hibernate: ERROR
Se você detectar um módulo configurado automaticamente que não deseja, ele pode ser desativado. Os documentos para isso podem ser encontrados aqui: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-disabling-specific-auto-configuration
Um exemplo seria:
fonte
Bem, há uma lista completa de ações possíveis descritas aqui: https://spring.io/blog/2018/12/12/how-fast-is-spring
Vou colocar as notas mais importantes do lado da primavera (ajustadas um pouco):
spring.config.location
(argumento da linha de comando ou propriedade do sistema, etc.). Exemplo para teste em IDE:spring.config.location=file://./src/main/resources/application.properties
.spring.jmx.enabled=false
(este é o padrão no Spring Boot 2.2)spring.main.lazy-initialization=true
no Spring Boot 2.2 (useLazyInitBeanFactoryPostProcessor
para Spring mais antigo).-noverify
. Considere também-XX:TieredStopAtLevel=1
(isso tornará o JIT mais lento, prejudicando o tempo de inicialização economizado).O mencionado
LazyInitBeanFactoryPostProcessor
(você pode usá-lo para o Spring 1.5 se não puder aplicar o sinalizadorspring.main.lazy-initialization=true
disponível no Spring 2.2):Você também pode usar (ou escrever seu próprio - é simples) algo para analisar o tempo de inicialização dos beans: https://github.com/lwaddicor/spring-startup-analysis
Espero que ajude!
fonte
No meu caso, havia muitos pontos de interrupção. Quando eu cliquei em "Mute Breakpoints" e reiniciei o aplicativo no modo de depuração, o aplicativo foi iniciado 10 vezes mais rápido.
fonte
Se você está tentando otimizar o retorno do desenvolvimento para testes manuais, recomendo fortemente o uso de devtools .
Basta recompilar - e o servidor será reiniciado (para Groovy, você só precisa atualizar o arquivo de origem). se você estiver usando um IDE (por exemplo, 'vscode'), ele pode compilar automaticamente seus arquivos java, portanto, apenas salvar um arquivo java pode iniciar uma reinicialização do servidor, indiretamente - e o Java torna-se tão simples quanto o Groovy nesse aspecto.
A beleza dessa abordagem é que a reinicialização incremental causa um curto-circuito em algumas das etapas de inicialização do zero - para que seu serviço volte a funcionar muito mais rapidamente!
Infelizmente, isso não ajuda com os tempos de inicialização para implantação ou teste de unidade automatizado.
fonte
AVISO: Se você não usa Hibernate DDL para geração automática de esquema de banco de dados e não usa cache L2, esta resposta NÃO se aplica a você. Avance.
Minha descoberta é que o Hibernate adiciona um tempo significativo para a inicialização do aplicativo. Desativando o cache L2 e a inicialização do banco de dados resulta na mais rápida do aplicativo Spring Boot. Deixe o cache ON para produção e desative-o para seu ambiente de desenvolvimento.
application.yml:
Resultado dos testes:
O cache L2 está LIGADO e
ddl-auto: update
O cache L2 está DESLIGADO e
ddl-auto: none
Agora me pergunto o que vou fazer com todo esse tempo livre
fonte
Acho estranho que ninguém tenha sugerido essas otimizações antes. Aqui estão algumas dicas gerais sobre como otimizar a construção e inicialização do projeto durante o desenvolvimento:
AVISOS
fonte
Para mim, parece que você está usando uma definição de configuração errada. Comece verificando myContainer e possíveis conflitos. Para determinar quem está usando mais recursos, você deve verificar os mapas de memória (veja a quantidade de dados!) Para cada dependência de cada vez - e isso leva muito tempo também ... (e privilégios SUDO). A propósito: você costuma testar o código em relação às dependências?
fonte