我有一个Spring Boot应用程序。我添加了很多依赖项(不幸的是,看起来我需要所有这些依赖项)并且启动时间上升了很多。只做SpringApplication.run(source, args)
需要10秒钟。
虽然与“使用”的内容相比可能没那么多,但我很不高兴它需要那么多,主要是因为它打破了开发流程。此时应用程序本身相当小,所以我假设大部分时间都与添加的依赖项有关,而不是应用程序类本身。
我认为问题是类路径扫描,但我不确定如何:
我认为enhancing Spring to have parallel bean initialization during startup可以加快速度,但是自2011年以来,该增强请求已经开放,没有任何进展。我在Spring Boot本身看到了一些其他的努力,例如Investigate Tomcat JarScanning speed improvements,但这是特定于Tomcat的,并且已被放弃。
这篇文章:
虽然针对集成测试,建议使用lazy-init=true
,但我不知道如何使用Java配置将此应用于Spring Boot中的所有bean - 这里有任何指针吗?
欢迎任何(其他)建议。
答案 0 :(得分:44)
Spring Boot会执行许多可能不需要的自动配置。因此,您可能只想缩小应用程序所需的自动配置范围。要查看包含的自动配置的完整列表,只需在DEBUG模式下运行org.springframework.boot.autoconfigure
的日志记录(logging.level.org.springframework.boot.autoconfigure=DEBUG
中的application.properties
)。另一个选项是使用--debug
选项运行spring boot应用程序:java -jar myproject-0.0.1-SNAPSHOT.jar --debug
输出中会出现类似的情况:
=========================
AUTO-CONFIGURATION REPORT
=========================
检查此列表并仅包含您需要的自动配置:
@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 {
代码是从this blog post复制的。
答案 1 :(得分:22)
到目前为止,投票最多的答案并没有错,但它没有深入到我喜欢的深度,也没有提供任何科学证据。 Spring Boot团队进行了一项练习,以减少Boot 2.0的启动时间,并且票证11226包含许多有用的信息。还有一个票据7939可以向条件评估添加时间信息,但它似乎没有特定的ETA。
调试启动启动的最有用,最有条理的方法是由Dave Syer完成的。 https://github.com/dsyer/spring-boot-startup-bench
我也有一个类似的用例,所以我采用了Dave与JMH进行微基准测试的方法并运行它。结果是boot-benchmark项目。我设计它可以用来测量任何Spring Boot应用程序的启动时间,使用bootJar
(之前在Boot 1.5中称为bootRepackage
)Gradle任务生成的可执行jar。随意使用它并提供反馈。
我的调查结果如下:
-XX:TieredStopAtLevel=1
可能会减慢您的第一次请求。答案 2 :(得分:6)
正如本问题/答案中所述,我认为最好的方法是不要只添加您认为需要的那些,而是排除您认为不需要的依赖项。
请参阅:Minimise Spring Boot Startup Time
总结:
您可以查看正在进行的操作,并启用调试日志记录,就像从命令行启动应用程序时指定--debug一样简单。您还可以在application.properties中指定debug = true。
此外,您可以将application.properties中的日志记录级别设置为:
logging.level.org.springframework.web:DEBUG logging.level.org.hibernate:错误
如果检测到您不想要的自动配置模块,则可以将其禁用。可在此处找到相关文档:http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-disabling-specific-auto-configuration
示例如下:
@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
答案 3 :(得分:4)
Spring Boot 2.2.M1 添加了支持Spring Boot中的惰性初始化的功能。
默认情况下,刷新应用程序上下文时,将创建上下文中的每个bean并注入其依赖项。相比之下,当将bean定义配置为延迟初始化时,将不会创建它,并且直到需要时才注入依赖项。
启用延迟初始化:将spring.main.lazy-initialization
设置为 true
有关更多详细信息,请检查Doc
答案 4 :(得分:4)
这里有完整的可能操作列表:https://spring.io/blog/2018/12/12/how-fast-is-spring
我将在Spring方面进行一些最重要的说明(稍作调整):
spring.config.location
(命令行参数或系统属性等)固定Spring Boot配置文件的位置。在IDE中进行测试的示例:spring.config.location=file://./src/main/resources/application.properties
。spring.jmx.enabled=false
,请关闭JMX(这是Spring Boot 2.2中的默认设置)spring.main.lazy-initialization=true
(对于较旧的Spring使用LazyInitBeanFactoryPostProcessor
)。-noverify
运行JVM。还考虑使用-XX:TieredStopAtLevel=1
(稍后会降低JIT速度,但会节省启动时间)。提到的LazyInitBeanFactoryPostProcessor
(如果无法应用Spring 2.2中可用的标记spring.main.lazy-initialization=true
,则可以在Spring 1.5中使用它:
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
definition.setLazyInit(true);
}
}
}
您还可以使用(或编写自己的-很简单)来分析bean的初始化时间:https://github.com/lwaddicor/spring-startup-analysis
希望有帮助!
答案 5 :(得分:-1)
如果您要优化手动测试的开发周转时间,强烈建议使用devtools。
使用spring-boot-devtools的应用程序将自动重启 每当类路径上的文件更改时。
只需重新编译-服务器将自行重启(对于Groovy,您只需要更新源文件)。如果您使用的是IDE(例如“ vscode”),它可能会自动编译Java文件,因此,仅保存Java文件就可以间接启动服务器重启-在这方面,Java与Groovy一样无缝。 / p>
这种方法的优点在于,增量重新启动会短路一些从头开始的启动步骤-这样您的服务将被备份并更快地运行!
不幸的是,这对部署或自动单元测试的启动时间没有帮助。
答案 6 :(得分:-1)
就我而言,断点太多。当我单击“静音断点”并以调试模式重新启动应用程序时,应用程序启动速度提高了10倍。
答案 7 :(得分:-2)
警告:如果您不使用Hibernate DDL来自动生成数据库模式,也不使用L2缓存,则此答案不适用于您。向前滚动。
我的发现是Hibernate为应用程序启动增加了大量时间。禁用L2缓存和database initialization可加快Spring Boot应用程序的启动速度。将缓存保留为生产状态,并在开发环境中将其禁用。
application.yml:
spring:
jpa:
generate-ddl: false
hibernate:
ddl-auto: none
properties:
hibernate:
cache:
use_second_level_cache: false
use_query_cache: false
测试结果:
L2缓存已打开,并且ddl-auto: update
INFO 5024 --- [restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 23331 ms
INFO 5024 --- [restartedMain] b.n.spring.Application : Started Application in 54.251 seconds (JVM running for 63.766)
L2缓存已关闭,并且ddl-auto: none
INFO 10288 --- [restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 9863 ms
INFO 10288 --- [restartedMain] b.n.spring.Application : Started Application in 32.058 seconds (JVM running for 37.625)
现在我想知道所有这些空闲时间该怎么办
答案 8 :(得分:-3)
我觉得很奇怪,以前没有人建议过这些优化。以下是在开发时优化项目构建和启动的一些一般技巧:
警告
答案 9 :(得分:-6)
对我而言,听起来你使用了错误的配置设置。 首先检查myContainer和可能的冲突。 要确定谁在使用最多的资源,每次检查每个依赖项的内存映射(请参阅数据量!) - 这需要大量时间,以及......(以及SUDO权限)。 顺便问一下:您是否经常针对依赖项测试代码?