加快Spring Boot启动时间
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加快Spring Boot启动时间相关的知识,希望对你有一定的参考价值。
我有一个Spring Boot应用程序。我添加了很多依赖项(不幸的是,看起来我需要所有这些依赖项)并且启动时间上升了很多。只是做一个SpringApplication.run(source, args)
需要10秒。
虽然这与“使用”相比可能没那么多,但我很不高兴它需要那么多,主要是因为它打破了开发流程。此时应用程序本身相当小,所以我假设大部分时间都与添加的依赖项有关,而不是与应用程序类本身有关。
我假设问题是类路径扫描,但我不知道如何:
- 确认是问题(即如何“调试”Spring Boot)
- 如果它真的是原因,我怎么能限制它,所以它变得更快?例如,如果我知道某些依赖项或包不包含Spring应扫描的任何内容,是否有办法限制它?
我认为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 - 这里有任何指针吗?
任何(其他)建议都会受到欢迎。
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复制的。
到目前为止,投票最多的答案并没有错,但它没有深入到我喜欢的深度,也没有提供任何科学证据。 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。随意使用它并提供反馈。
我的调查结果如下:
- CPU很重要。很多。
- 使用-Xverify:none启动JVM有很大帮助。
- 排除不必要的自动配置有帮助。
- 戴夫推荐JVM参数-XX:TieredStopAtLevel=1,但我的测试没有显示出明显的改进。此外,
-XX:TieredStopAtLevel=1
可能会减慢您的第一个请求。 - 主机名解析的reports很慢,但我没有发现它对我测试的应用程序有问题。
正如在这个问题/答案中所描述的,我认为最好的方法是不要只添加您认为需要的那些,而是排除您不需要的依赖项。
见:Minimise Spring Boot Startup Time
综上所述:
您可以看到正在进行的操作,并启用调试日志记录,就像从命令行启动应用程序时指定--debug一样简单。您还可以在application.properties中指定debug = true。
此外,您可以在application.properties中设置日志记录级别,如下所示:
logging.level.org.springframework.web:DEBUG logging.level.org.hibernate:ERROR
如果检测到您不想要的自动配置模块,则可以禁用它。这方面的文档可以在这里找到: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 {
}
Spring Boot 2.2.M1增加了在Spring Boot中支持Lazy Initialization的功能。
默认情况下,在刷新应用程序上下文时,将创建上下文中的每个bean并注入其依赖项。相比之下,当bean定义被配置为懒惰地初始化时,它将不会被创建,并且在需要之前不会注入其依赖项。
启用延迟初始化将spring.main.lazy-initialization
设置为true
有关详细信息,请查看Doc
如果您正在尝试优化手动测试的开发周转,我强烈建议使用devtools。
使用spring-boot-devtools的应用程序将在类路径上的文件发生更改时自动重新启动。
只需重新编译 - 服务器将自动重启(对于Groovy,您只需要更新源文件)。如果您正在使用IDE(例如'vscode'),它可能会自动编译您的java文件,因此只需保存一个java文件就可以间接启动服务器重启 - 而Java在这方面就像Groovy一样无缝。
这种方法的优点在于增量重启会使一些从头开始的启动步骤短路 - 这样您的服务就可以更快地备份和运行!
不幸的是,这对部署或自动化单元测试的启动时间没有帮助。
警告:如果您不使用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缓存是ON和
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缓存是OFF和
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)
现在我想知道我将如何处理所有这些空闲时间
我觉得很奇怪之前没有人建议这些优化。以下是开发时优化项目构建和启动的一些常规技巧:
- 从防病毒扫描程序中排除开发目录: 项目目录 构建输出目录(如果它在项目目录之外) IDE索引目录(例如〜/ .IntelliJIdea2018.3) 部署目录(Tomcat中的webapps)
- 升级硬件。使用更快的CPU和RAM,更好的互联网连接(用于下载依赖项)和数据库连接,切换到SSD。视频卡没关系。
警告
- 第一种选择是降低安全性的代价。
- 第二种选择需要花钱(显然)。
对我而言,听起来你使用了错误的配置设置。首先检查myContainer和可能的冲突。要确定谁在使用最多的资源,每次检查每个依赖项的内存映射(请参阅数据量!) - 这需要大量时间,以及......(以及SUDO权限)。顺便说一句:您是否经常针对依赖项测试代码?
以上是关于加快Spring Boot启动时间的主要内容,如果未能解决你的问题,请参考以下文章
一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式
解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)(代码片段
一张图帮你记忆,Spring Boot 应用在启动阶段执行代码的几种方式
一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式