Tengo una aplicación Spring Boot. Agregué muchas dependencias (desafortunadamente, parece que las necesito todas) y el tiempo de inicio aumentó bastante. Solo hacer una SpringApplication.run(source, args)
toma 10 segundos.
Si bien eso puede no ser mucho en comparación con lo que estamos "acostumbrados", no me satisface que requiera tanto, principalmente porque rompe el flujo de desarrollo. La aplicación en sí es bastante pequeña en este punto, así que supongo que la mayor parte del tiempo está relacionada con las dependencias agregadas, no con las clases de la aplicación en sí.
Supongo que el problema es el escaneo de classpath, pero no estoy seguro de cómo:
- Confirme que ese es el problema (es decir, cómo "depurar" Spring Boot)
- Si realmente es la causa, ¿cómo puedo limitarlo para que sea más rápido? Por ejemplo, si sé que alguna dependencia o paquete no contiene nada que Spring debería estar escaneando, ¿hay alguna forma de limitar eso?
Supongo que mejorar Spring para que tenga una inicialización de bean paralelo durante el inicio aceleraría las cosas, pero esa solicitud de mejora ha estado abierta desde 2011, sin ningún progreso. Veo algunos otros esfuerzos en Spring Boot, como Investigar mejoras de velocidad de Tomcat JarScanning , pero eso es específico de Tomcat y se ha abandonado.
Este artículo:
aunque está dirigido a pruebas de integración, sugiere usar lazy-init=true
, sin embargo, no sé cómo aplicar esto a todos los beans en Spring Boot usando la configuración de Java, ¿algún consejo aquí?
Cualquier (otra) sugerencia será bienvenida.
fuente
@ComponentScan
se analizarán. Otra cosa es asegurarse de no haber habilitado el registro de depuración o seguimiento, ya que generalmente el registro es lento, muy lento.Respuestas:
Spring Boot realiza muchas configuraciones automáticas que pueden no ser necesarias. Por lo tanto, es posible que desee limitar solo la configuración automática que se necesita para su aplicación. Para ver la lista completa de la configuración automática incluida, simplemente ejecute el registro
org.springframework.boot.autoconfigure
en modo DEBUG (logging.level.org.springframework.boot.autoconfigure=DEBUG
enapplication.properties
). Otra opción es ejecutar la aplicación Spring Boot con la--debug
opción:java -jar myproject-0.0.1-SNAPSHOT.jar --debug
Habría algo como esto en la salida:
Inspeccione esta lista e incluya solo las configuraciones automáticas que necesita:
El código se copió de esta publicación de blog .
fuente
La respuesta más votada hasta ahora no es incorrecta, pero no entra en la profundidad que me gustaría ver y no proporciona evidencia científica. El equipo de Spring Boot realizó un ejercicio para reducir el tiempo de inicio de Boot 2.0 y el ticket 11226 contiene mucha información útil. También hay un ticket 7939 abierto para agregar información de tiempo a la evaluación de la condición, pero no parece tener una ETA específica.
El enfoque más útil y metódico para depurar el inicio de arranque lo ha realizado Dave Syer. https://github.com/dsyer/spring-boot-startup-bench
También tuve un caso de uso similar, así que tomé el enfoque de microevaluación comparativa de Dave con JMH y lo seguí. El resultado es el proyecto de referencia de arranque . Lo diseñé de tal manera que pueda usarse para medir el tiempo de inicio de cualquier aplicación Spring Boot, usando el jar ejecutable producido por
bootJar
(anteriormente llamadobootRepackage
en Boot 1.5) la tarea Gradle. Siéntase libre de usarlo y enviar comentarios.Mis hallazgos son los siguientes:
-XX:TieredStopAtLevel=1
probablemente ralentizaría su primera solicitud.fuente
minimal
o simplemente se puede suministrar el frasco? Intenté hacer lo primero pero no llegué muy lejos.-Xverify:none
en producción ya que rompe la verificación del código y puede tener problemas.-XX:TieredStopAtLevel=1
está bien si ejecuta una aplicación durante un período breve (unos segundos), de lo contrario, será menos productiva, ya que proporcionará a la JVM optimizaciones de ejecución prolongada.Use of -Xverify:none is unsupported.
¿qué significa?Spring Boot 2.2.M1 ha agregado una función para admitir la inicialización diferida en Spring Boot.
De forma predeterminada, cuando se actualiza un contexto de aplicación, se crean todos los beans del contexto y se inyectan sus dependencias. Por el contrario, cuando se configura una definición de bean para que se inicialice de forma diferida, no se creará y sus dependencias no se inyectarán hasta que se necesite.
Habilitar la inicialización diferida establecida
spring.main.lazy-initialization
en verdaderoCuándo habilitar la inicialización diferida La inicialización diferida puede ofrecer mejoras significativas en el tiempo de inicio, pero también existen algunas desventajas notables y es importante habilitarla con cuidado
Para obtener más detalles, consulte Doc.
fuente
Como se describe en esta pregunta / respuesta, creo que el mejor enfoque es, en lugar de agregar solo las que cree que necesita, excluir las dependencias que sabe que no necesita.
Ver: Minimizar el tiempo de inicio de Spring Boot
En resumen:
Puede ver lo que está sucediendo bajo las sábanas y habilitar el registro de depuración tan simple como especificar --debug al iniciar la aplicación desde la línea de comandos. También puede especificar debug = true en su application.properties.
Además, puede establecer el nivel de registro en application.properties tan simple como:
logging.level.org.springframework.web: DEBUG logging.level.org.hibernate: ERROR
Si detecta un módulo configurado automáticamente que no desea, puede deshabilitarlo. Los documentos para esto se pueden encontrar aquí: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-disabling-specific-auto-configuration
Un ejemplo se vería así:
fuente
Bueno, hay una lista completa de posibles acciones descritas aquí: https://spring.io/blog/2018/12/12/how-fast-is-spring
Pondré las notas más importantes del lado de Spring (ajustado un poco):
spring.config.location
(argumento de línea de comando o propiedad del sistema, etc.). Ejemplo de prueba en IDE:spring.config.location=file://./src/main/resources/application.properties
.spring.jmx.enabled=false
(este es el valor predeterminado en Spring Boot 2.2)spring.main.lazy-initialization=true
en Spring Boot 2.2 (se usaLazyInitBeanFactoryPostProcessor
para Spring anterior).-noverify
. También considere-XX:TieredStopAtLevel=1
(eso ralentizará el JIT más adelante a expensas del tiempo de inicio guardado).Lo mencionado
LazyInitBeanFactoryPostProcessor
(puede usarlo para Spring 1.5 si no puede aplicar la banderaspring.main.lazy-initialization=true
disponible desde Spring 2.2):También puede usar (o escribir el suyo propio, es simple) algo para analizar el tiempo de inicialización de los beans: https://github.com/lwaddicor/spring-startup-analysis
¡Espero eso ayude!
fuente
En mi caso, hubo demasiados puntos de interrupción. Cuando hice clic en "Mute Breakpoints" y reinicié la aplicación en modo de depuración, la aplicación se inició 10 veces más rápido.
fuente
Si está intentando optimizar el tiempo de respuesta del desarrollo para las pruebas manuales, le recomiendo encarecidamente el uso de devtools .
Simplemente vuelva a compilar, y el servidor se reiniciará solo (para Groovy solo necesita actualizar el archivo fuente). si está utilizando un IDE (por ejemplo, 'vscode'), puede compilar automáticamente sus archivos java, por lo que simplemente guardar un archivo java puede iniciar un reinicio del servidor, indirectamente, y Java se vuelve tan fluido como Groovy en este sentido.
La belleza de este enfoque es que el reinicio incremental cortocircuita algunos de los pasos de inicio desde cero, por lo que su servicio volverá a funcionar mucho más rápido.
Desafortunadamente, esto no ayuda con los tiempos de inicio para la implementación o las pruebas unitarias automatizadas.
fuente
ADVERTENCIA: Si no usa Hibernate DDL para la generación automática de esquemas de base de datos y no usa la caché L2, esta respuesta NO se aplica a usted. Desplácese hacia adelante.
Mi hallazgo es que Hibernate agrega un tiempo significativo al inicio de la aplicación. La desactivación de la inicialización de la base de datos y el caché L2 da como resultado un inicio más rápido de la aplicación Spring Boot. Deje el caché activado para producción y desactívelo para su entorno de desarrollo.
application.yml:
Resultados de la prueba:
La caché L2 está ACTIVADA y
ddl-auto: update
La caché L2 está desactivada y
ddl-auto: none
Ahora me pregunto que haré con todo este tiempo libre
fuente
Me parece extraño que nadie sugiriera estas optimizaciones antes. A continuación, se ofrecen algunos consejos generales sobre cómo optimizar la creación y el inicio del proyecto durante el desarrollo:
ADVERTENCIAS
fuente
A mí me parece que estás usando una configuración incorrecta. Empiece por comprobar myContainer y los posibles conflictos. Para determinar quién está usando la mayor cantidad de recursos, debe verificar los mapas de memoria (¡vea la cantidad de datos!) Para cada dependencia a la vez, y eso también requiere mucho tiempo ... (y privilegios SUDO). Por cierto: ¿suele probar el código con las dependencias?
fuente