加快Spring Boot启动时间

ste*_*ain 90 java performance startup spring-boot

我有一个Spring Boot应用程序.我添加了很多依赖项(不幸的是,看起来我需要所有这些依赖项)并且启动时间上升了很多.只SpringApplication.run(source, args)需要10秒钟.

虽然这与"使用"相比可能没那么多,但我很不高兴它需要那么多,主要是因为它打破了开发流程.此时应用程序本身相当小,所以我假设大部分时间都与添加的依赖项有关,而不是与应用程序类本身有关.

我假设问题是类路径扫描,但我不知道如何:

  • 确认是问题(即如何"调试"Spring Boot)
  • 如果它真的是原因,我怎么能限制它,所以它变得更快?例如,如果我知道某些依赖项或包不包含Spring应扫描的任何内容,是否有办法限制它?

我假设这个:

会加快速度,但现在甚至都没有进行分类.我在Spring Boot本身看到了一些其他的努力,例如:

但这看起来特定于Tomcat.

本文:

虽然针对集成测试,建议使用lazy-init=true,但是我不知道如何使用Java配置将这个应用于Spring Boot中的所有bean - 这里有任何指针吗?

任何(其他)建议都会受到欢迎.

lub*_*nac 54

Spring Boot进行了许多可能不需要的自动配置.因此,您可能只想缩小应用程序所需的自动配置范围.要查看包含的自动配置的完整列表,只需org.springframework.boot.autoconfigure在DEBUG模式(logging.level.org.springframework.boot.autoconfigure=DEBUGin application.properties)中运行日志记录.另一种选择是使用--debug选项运行spring boot应用程序:java -jar myproject-0.0.1-SNAPSHOT.jar --debug

在输出中会有这样的东西:

=========================
AUTO-CONFIGURATION REPORT
=========================
Run Code Online (Sandbox Code Playgroud)

检查此列表并仅包含您需要的自动配置:

@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 {
Run Code Online (Sandbox Code Playgroud)

代码是从此博客文章中复制而来.

  • 如何处理私有配置类? (3认同)

Abh*_*kar 30

到目前为止,投票最多的答案并没有错,但它没有深入到我喜欢的深度,也没有提供任何科学证据.Spring Boot团队进行了一项练习,以减少Boot 2.0的启动时间,而11226票据包含许多有用的信息.还有一个票据7939可以添加时间信息以进行条件评估,但它似乎没有特定的ETA.

调试启动启动的最有用,最有条理的方法是由Dave Syer完成的.https://github.com/dsyer/spring-boot-startup-bench

我也有一个类似的用例,所以我采用了Dave与JMH进行微基准测试的方法并运行它.结果是启动基准测试项目.我设计它可以用来测量任何Spring Boot应用程序的启动时间,使用由bootJar(先前bootRepackage在Boot 1.5中调用)Gradle任务生成的可执行jar .随意使用它并提供反馈.

我的调查结果如下:

  1. CPU很重要.很多.
  2. 使用-Xverify:none启动JVM 会有很大帮助.
  3. 排除不必要的自动配置有帮助.
  4. Dave推荐JVM参数-XX:TieredStopAtLevel = 1,但是我的测试没有显示出显着的改进.此外,-XX:TieredStopAtLevel=1可能会减慢您的第一个请求.
  5. 报道称主机名解析速度很慢,但我没有发现它对我测试的应用程序有问题.

  • 不要在生产环境中运行“-Xverify:none”,因为它会破坏代码验证,并且您可能会遇到麻烦。如果您运行应用程序的时间很短(几秒钟),则“-XX:TieredStopAtLevel=1”是可以的,否则它将降低生产力,因为它将为 JVM 提供长时间运行的优化。 (4认同)
  • 除此之外,您能否添加一个示例,说明有人如何将您的基准测试用于自定义应用程序?是否必须将其添加为类似于“最小”的项目,还是可以简单地提供 jar?我试图做前者,但没有走得很远。 (2认同)
  • oracle doc列出了`-Xverify:none的使用不受支持。'是什么意思? (2认同)
  • 许多池(当然是 Oracle UCP,但在我的测试中还包括 Hikari 和 Tomcat)对池中的数据进行加密。我实际上不知道他们是否正在加密连接信息或包装流。无论如何,加密使用随机数生成,因此拥有高可用性、高吞吐量的熵源会在性能方面产生显着差异。 (2认同)

pcz*_*eus 9

正如本问题/答案中所述,我认为最好的方法是不要只添加您认为需要的那些,而是排除您不需要的依赖项.

请参阅:最小化Spring Boot启动时间

综上所述:

您可以看到正在进行的操作,并启用调试日志记录,就像从命令行启动应用程序时指定--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 {
}
Run Code Online (Sandbox Code Playgroud)


Nir*_*ane 9

Spring Boot 2.2.M1 添加了支持Spring Boot中的惰性初始化的功能。

缺省情况下,刷新应用程序上下文时,将创建上下文中的每个bean并注入其依赖项。相比之下,当将bean定义配置为延迟初始化时,将不会创建它,并且直到需要时才注入其依赖项。

启用惰性初始化设置spring.main.lazy-initializationtrue

有关更多详细信息,请检查Doc

  • 如果启用延迟初始化,第一次加载速度非常快,但是当客户端第一次访问时可能会注意到一些延迟。我真的推荐这个用于开发而不是生产。 (5认同)
  • 正如 @IsuruDewasurendra 所建议的,这不是推荐的方式,它会显着增加应用程序开始提供负载时的延迟。 (2认同)

Prz*_*wak 6

好吧,这里描述了完整的可能操作列表:https : //spring.io/blog/2018/12/12/how-fast-is-spring

我将把 Spring 方面最重要的笔记(稍微调整一下):

  • Spring Boot web starters 中的类路径排除:
    • 休眠验证器
    • Jackson(但 Spring Boot 执行器依赖于它)。如果您需要 JSON 渲染,请使用 Gson(仅适用于开箱即用的 MVC)。
    • Logback:改用 slf4j-jdk14
  • 使用弹簧上下文索引器。它不会增加太多,但每一点都有帮助。
  • 如果您负担不起,请不要使用执行器。
  • 使用 Spring Boot 2.1 和 Spring 5.1。可用时切换到 2.2 和 5.2。
  • 使用spring.config.location(命令行参数或系统属性等)修复 Spring Boot 配置文件的位置。在 IDE 中进行测试的示例:spring.config.location=file://./src/main/resources/application.properties.
  • 如果不需要,请关闭 JMX spring.jmx.enabled=false(这是 Spring Boot 2.2 中的默认设置)
  • 默认情况下使 bean 定义为惰性。spring.main.lazy-initialization=trueSpring Boot 2.2 中有一个新标志(LazyInitBeanFactoryPostProcessor用于旧的 Spring)。
  • 解压胖 jar 并使用显式类路径运行。
  • 使用-noverify. 还要考虑-XX:TieredStopAtLevel=1(这将在稍后以节省的启动时间为代价减慢 JIT)。

提到的LazyInitBeanFactoryPostProcessor(如果您不能应用spring.main.lazy-initialization=trueSpring 2.2 提供的标志,您可以将它用于 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);
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用(或编写自己的 - 这很简单)一些东西来分析 bean 初始化时间:https : //github.com/lwaddicor/spring-startup-analysis

希望能帮助到你!


小智 -10

对我来说,这听起来像是您使用了错误的配置设置。首先检查 myContainer 和可能的冲突。要确定谁使用了最多的资源,您必须一次检查每个依赖项的内存映射(查看数据量!) - 这也需要大量时间......(以及 SUDO 权限)。顺便说一句:您通常会针对依赖项测试代码吗?