Accélérer le démarrage de Spring Boot

J’ai une application Spring Boot. J’ai ajouté beaucoup de dépendances (malheureusement, je les ai toutes besoin) et le temps de démarrage a beaucoup augmenté. Un SpringApplication.run(source, args) prend 10 secondes.

Bien que cela puisse ne pas être beaucoup comparé à ce qui est “utilisé”, je suis malheureux que cela prenne autant, surtout parce que cela brise le stream de développement. L’application elle-même est plutôt petite à ce stade, donc je suppose que la plupart du temps, elle est liée aux dépendances ajoutées, pas aux classes d’applications elles-mêmes.

Je suppose que le problème est l’parsing de classpath, mais je ne sais pas comment:

  • Confirmez que c’est le problème (par exemple, comment “déboguer” le démarrage du spring)
  • Si c’est vraiment la cause, comment puis-je la limiter, alors ça va plus vite? Par exemple, si je sais qu’une dépendance ou un package ne contient aucun élément que Spring doit parsingr, existe-t-il un moyen de le limiter?

Je suppose que:

  • https://jira.spring.io/browse/SPR-8767

serait accélérer les choses, mais ce n’est même pas sortingé à ce stade. Je vois d’autres efforts dans Spring Boot lui-même, par exemple:

  • https://github.com/spring-projects/spring-boot/issues/1610

mais cela semble spécifique à Tomcat.

Cet article:

  • http://www.nurkiewicz.com/2010/12/speeding-up-spring-integration-tests.html

Bien que visant à des tests d’intégration, suggère d’utiliser lazy-init=true , mais je ne sais pas comment l’appliquer à tous les beans dans Spring Boot en utilisant la configuration Java – des pointeurs ici?

Toute (autre) suggestion serait la bienvenue.

Spring Boot fait beaucoup de configuration automatique qui peut ne pas être nécessaire. Ainsi, vous souhaiterez peut-être limiter la configuration automatique requirejse pour votre application. Pour voir la liste complète de la configuration automatique incluse, exécutez simplement la journalisation de org.springframework.boot.autoconfigure en mode DEBUG ( logging.level.org.springframework.boot.autoconfigure=DEBUG dans application.properties ). Une autre option consiste à exécuter l’application Spring Boot avec l’option --debug : java -jar myproject-0.0.1-SNAPSHOT.jar --debug

Il y aurait quelque chose comme ça dans la sortie:

 ========================= AUTO-CONFIGURATION REPORT ========================= 

Inspectez cette liste et n’incluez que les autoconfigurations dont vous avez besoin:

 @Configuration @Import({ DispatcherServletAutoConfiguration.class, EmbeddedServletContainerAutoConfiguration.class, ErrorMvcAutoConfiguration.class, HttpEncodingAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class, ServerPropertiesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, ThymeleafAutoConfiguration.class, WebMvcAutoConfiguration.class, WebSocketAutoConfiguration.class, }) public class SampleWebUiApplication { 

Le code a été copié depuis cet article de blog .

Comme décrit dans cette question / réponse, je pense que la meilleure approche consiste à exclure les dépendances dont vous avez besoin.

See: Minimize Spring Boot Startup Time

En résumé:

Vous pouvez voir ce qui se passe sous les couvertures et activer la journalisation du débogage en spécifiant simplement –debug lors du démarrage de l’application à partir de la ligne de commande. Vous pouvez également spécifier debug = true dans votre application.properties.

En outre, vous pouvez définir le niveau de consignation dans application.properties aussi simplement que:

logging.level.org.springframework.web: DEBUG logging.level.org.hibernate: ERREUR

Si vous détectez un module configuré automatiquement que vous ne souhaitez pas, il peut être désactivé. Les documents pour cela peuvent être trouvés ici: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-disabling-specific-auto-configuration

Un exemple ressemblerait à ceci:

 @Configuration @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class MyConfiguration { } 

La réponse la plus votée à ce jour n’est pas erronée, mais elle n’entre pas dans la profondeur que j’aime voir et ne fournit aucune preuve scientifique. L’équipe Spring Boot a fait un exercice pour réduire le temps de démarrage de Boot 2.0, et le ticket 11226 contient beaucoup d’informations utiles. Le ticket 7939 est également ouvert pour append des informations de synchronisation à l’évaluation de la condition, mais il ne semble pas avoir d’ETA spécifique.

L’approche la plus utile et méthodique pour le débogage Le démarrage du démarrage a été effectué par Dave Syer. https://github.com/dsyer/spring-boot-startup-bench

J’avais un cas d’utilisation similaire, alors j’ai adopté l’approche de microbenchmaring de Dave avec JMH et je l’ai utilisée. Le résultat est le projet boot-benchmark . Je l’ai conçu de telle sorte qu’il puisse être utilisé pour mesurer le temps de démarrage de toute application Spring Boot, en utilisant le fichier exécutable produit par bootJar (précédemment appelé bootRepackage dans Boot 1.5). N’hésitez pas à l’utiliser et à fournir des commentaires.

Mes constatations sont les suivantes:

  1. Le CPU est important. Beaucoup.
  2. Démarrer la JVM avec -Xverify: aucune aide significative.
  3. L’exclusion de la configuration automatique inutile aide.
  4. Dave a recommandé l’argument JVM -XX: TieredStopAtLevel = 1 , mais mes tests n’ont pas montré d’amélioration significative avec cela. De même, -XX:TieredStopAtLevel=1 ralentirait probablement votre première requête.
  5. Il y a eu des rapports de résolution de noms d’hôte lents, mais je n’ai pas trouvé que c’était un problème pour les applications que j’ai testées.

Il n’existe qu’un seul moyen garanti de déterminer ce qui se passe ici, à savoir créer un profil de votre application et rechercher les points critiques à l’origine du problème.

Je recommande d’utiliser YourKit. Il a une très bonne intégration IDE afin que vous puissiez profiler votre application depuis Eclipse ou autre. Vois ici

https://www.yourkit.com/docs/java/help/local_profiling.jsp

Vous serez très rapidement en mesure de voir ce qui cause le problème, puis vous pouvez poster ici des solutions possibles.

Vous pouvez essayer ma bibliothèque FastClasspathScanner . Je ne sais pas si vous pouvez faire fonctionner Spring avec ça, mais il scanne le classpath beaucoup plus rapidement que Spring.

Pour moi, il semble que vous utilisiez un mauvais paramètre de configuration. Commencez par vérifier myContainer et les conflits éventuels. Pour déterminer qui utilise le plus de ressources, vous devez vérifier les cartes mémoire (voir la quantité de données!) Pour chaque dépendance à la fois – et cela prend également beaucoup de temps … (et les privilèges SUDO). Au fait, testez-vous généralement le code contre les dépendances?