Spring Boot 2.2中的延迟初始化


译者的话:由于Spring框架是构建CUBA的主要框架之一,因此有关Spring新功能的新闻并没有引起我们的注意。 延迟初始化是减少应用程序首次启动时间的一种方法,这在我们微服务广泛使用的时代是一个重要指标。 对于那些喜欢看观看视频的人,乔什·朗 Josh Long)有10分钟的演讲主题。


最近宣布的Spring Boot 2.2的第一个里程碑版本增加了对延迟初始化的支持。 在本文中,我们将研究新功能并说明如何启用它。


懒惰意味着什么?


自从11年前将其源代码移至git以来,Spring框架一直支持延迟初始化。 默认情况下,在更新应用程序上下文时,将重新创建每个bean并实现其依赖关系。 相反,如果将bin配置为延迟初始化,则在必要之前将不会创建该bin,也不会放下其依赖项。


启用延迟初始化


在任何版本的Spring Boot中,如果您不介意使用BeanFactoryPostProcessor弄脏手,则可以启用延迟初始化。 Spring Boot 2.2通过引入新属性spring.main.lazy-initialization (在SpringApplicationSpringApplicationBuilder中也存在等效的方法)来简化此过程。 当此属性设置为true ,将配置应用程序Bean使用延迟初始化。


延迟初始化的好处


延迟初始化可以显着减少应用程序的启动时间,因为在此阶段加载的类更少,创建的箱更少。 例如,使用Actuator和Spring Security的小型Web应用程序通常启动2.5秒。 并通过延迟初始化,此过程需要2秒钟。 确切的加速度值将根据应用程序的不同而有所不同,这取决于容器的依赖关系图的结构。


译者注:我运行了这个示例 ,在依赖项中编写了Spring Boot 2.2,并且在没有延迟初始化的情况下启动时间为3秒,而在没有延迟4的情况下。我认为,在更严重的应用程序中,由于使用了延迟初始化,启动时间会大大增加我们不会看到。 更新:alek_sys的建议下,禁用了数据库模式的验证和更新,并打开了两种情况下的延迟JPA初始化-事实证明是在2.7和3.7秒之前Started WebApplication in...Started WebApplication in...


那么DevTools呢?


Spring Boot DevTools提供了显着的开发加速。 DevTools不会在每次更改时重新启动JVM和应用程序,而是在同一JVM中对应用程序进行“热重启”。 这种重新启动的一个显着优点是,它为JIT提供了优化应用程序启动时执行的代码的机会。 几次重启后,2.5秒的初始​​时间减少了近80%,为500 ms。 使用延迟初始化,情况会更好。 设置spring.main.lazy-initialization属性将直接在IDE中显示等于400 ms的重启时间。


延迟初始化的反面


如上所示,延迟初始化的包含可以严重减少应用程序的启动时间。 也许您会不可避免地渴望不断使用它,或者至少您会想知道为什么默认情况下不启用惰性初始化。 有几种可能的负面影响,最好立即加以澄清。


在需要它们之前,不会加载类并且不会创建bin的事实掩盖了早在应用程序启动阶段就已经发现的问题。 例如,可能是缺少所需的类,内存溢出或与错误的配置相关的错误。


在Web应用程序中,惰性配置可能会增加导致bin初始化的HTTP请求的延迟。 通常这是第一个请求,但是可能会有其他有害影响影响负载平衡或自动缩放。


这东西包括在内吗?


如果不确定延迟初始化对您的应用程序有多大影响,或者您想检查框架的其他方面是否适合您并满足您的需要,那么使用调试器对此很有用。 通过在bin构造函数上设置断点,您可以看到bin初始化的确切时间。 例如,在用Spring Boot编写并启用了延迟初始化的Web应用程序中,您可以看到直到向DispatcerServlet Spring MVC或对DispatchHandler Spring WebFlux的第一个请求时,才创建带有@Controller批注的bean。


何时开启延迟初始化?


正如我们在上面看到的,惰性初始化在应用程序启动期间提供了显着的改进,但是也有缺点,因此您需要非常小心地使用此功能。


惰性初始化可以带来收益(几乎没有开销)的一个领域是应用程序开发过程。 在编写应用程序时,延迟初始化与DevTools结合使用可减少重新启动时间,从而可以节省大量时间。


在集成测试中,您还能从其他地方获得使用惰性初始化的好处。 您可能已经在使用“切片”测试来通过限制某些类型的测试中初始化的bean的数量来减少执行时间。 延迟初始化提供了另一个获得相同结果的机会。 如果您在为“切片”测试更改应用程序结构时处于错误的位置,或者对于您的特定测试,没有合适的“切片”,那么延迟初始化的包含会将bin的数量限制为仅在测试中使用的bin。 这将减少测试执行时间,尤其是在开发过程中它们在隔离环境中运行时。


最后在产品上打开延迟初始化。 而且,如果您决定这样做,请谨慎行事。 对于Web应用程序,容器管理器可以依靠/health入口点,该入口点通常响应速度非常快,但是请记住,首次调用可能比平时花费更长的时间。 您还必须记住分配给JVM的内存大小,以便在初始化所有组件时不会遇到溢出。

Source: https://habr.com/ru/post/zh-CN445592/


All Articles