如何让SpringBoot启动更快一点
这篇文章主要介绍"如何让SpringBoot启动更快一点"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"如何让SpringBoot启动更快一点"文章能帮助大家解决问题。
我使用的是 OpenJDK 11。
❯ java --version
openjdk 11.0.1 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
可以按照下面这样运行基准测试。运行起来可能需要一些时间,下面会执行所有的测试。
❯ ./mvnw clean package
❯ (cd benchmarks/; java -jar target/benchmarks.jar)
1. FluxBaseline
我使用 SpringInitializr 创建项目,仅包含 Reactive Web。接下来,我会写一个 WebMVC 风格的极简controller。
@SpringBootApplication
@RestController
public class DemoApplication {
@GetMapping("/")
public String home() {
return "Hello";
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
↓Spring Boot 版本是 2.1.0.RELEASE。
↓启动结果 2.938 ± 0.287 s/op。
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
现在,以这个结果作为基线。让我们从这里开始。
2. WebMVC
↓我很好奇为什么要用 WebMVC 而不是 WebFlux? 我尝试了一下。也许仅仅是为了比较 Tomcat 和 Netty?
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case02_Web ss 10 3.281 ± 0.342 s/op
WebFlux 快了一点,难道不是吗?
3. spring-context-indexer
接下来,我试了 spring-context-indexer,似乎创建了 component index。
↓嗯…慢了一点点?
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case03_WithContextIndexer ss 10 3.063 ± 0.102 s/op
↓我检查了 spring.components,发现只包含了一个组件。了解...我应该尝试更大一点的项目,这样才能看到效果。
#
#Sun Nov 04 18:42:59 JST 2018
com.example.DemoApplication=org.springframework.stereotype.Component
4. 惰性初始化
尝试了惰性初始化。
@Configuration
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
beanFactory.getBeanDefinition(beanName).setLazyInit(true);
}
}
}
↓查看结果,启动变快了一点。
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case04_WithLazyInit ss 10 2.844 ± 0.129 s/op
5. NoVerify
运行加 -noverify 选项:
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case05_WithNoVerifyOption ss 10 2.582 ± 0.060 s/op
启动变得快了一点。不知道为什么有这个结果,稍后需要仔细了解一下。
6. TieredStopAtLevel
运行加 -XX:TieredStopAtLevel=1 选项:
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case06_WithTieredStopAtLevel1Option ss 10 1.980 ± 0.037 s/op
嗯,快多了!减少了几乎2秒。还是不知道这个参数有什么含义,稍后需要仔细了解一下。
7. 指定 SpringConfigLocation 参数
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case07_WithSpringConfigLocationOption ss 10 3.026 ± 0.139 s/op
嗯,又变慢了。
8. 关闭 JMX
运行加 -Dspring.jmx.enabled=false 选项:
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case08_WithJmxDisabledOption ss 10 2.877 ± 0.097 s/op
变得快了一点。
9. 取消 Logback
从这里开始,我开始减少函数库。开始,取消 Logback:
结果如下Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case09_WithoutLogback ss 10 2.904 ± 0.096 s/op
嗯…似乎有一点点改进?
10. 取消 Jackson
接下来是 Jackson
结果如下:
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case10_WithoutJackson ss 10 2.789 ± 0.093 s/op
结果变快了一点。
11. 取消 HibernateValidator
结果如下:
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case11_WithoutHibernateValidator ss 10 2.857 ± 0.084 s/op
也有一点效果。
到这里为止,不再取消函数库了。
12. AppCDS
AppCDS (Application Class Data Sharing) 是 Oracle JDK 的一个企业版功能。OpenJDK 10 开始包含了这个功能。
看起来 AppCDS 转储信息存到了一个共享压缩文件,所以启动时间变短了。
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case12_WithAppCds ss 10 2.957 ± 0.079 s/op
嗯…并没有变快…然后我阅读了CDS的相关文章,找到原因了。
SpringBoot FatJAR 不在 CDS 管理范围内。
13. 使用 Thin Launcher 的 Flux
嗯,对不起,"Exploded" 基准测试错了。我曾经试着使用 FatJAR,但是 CDS 不能这么干。所以,我转而使用 Thin Launcher,所以 "Exploded" 就变成了 "Thin Launche"。
使用 CDS 以前,我会测试使用 Thin Launcher 打包 JAR 文件的启动速度。
尽管我使用 Thin Launcher 打包 app,但并没有使用 Thin Launcher 启动类,而是使用 Main class 让启动尽可能快一些。
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case13_Exploded ss 10 2.476 ± 0.091 s/op
嗯,快了一点,对吗?
14. Thin Launcher + CDS
现在,我要使用 AppCDS 。
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case14_ExplodedWithAppCds ss 10 1.535 ± 0.036 s/op
喔!变得更快了!
15. 所有操作都上
最终,我把所有操作都用上。
1
2
3Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case15_AllApplied ss 10 0.801 ± 0.037 s/op
小于1秒钟!(∩´∀——)∩耶
更进一步
在 Dave 的视频中,他提到了"函数式 Bean 定义",尝试仅使用 Spring 不用 SpringBoot,app变得更快了。其中的道理还需要进一步了解。
结果:
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case02_Web ss 10 3.281 ± 0.342 s/op
MyBenchmark.case03_WithContextIndexer ss 10 3.063 ± 0.102 s/op
MyBenchmark.case04_WithLazyInit ss 10 2.844 ± 0.129 s/op
MyBenchmark.case05_WithNoVerifyOption ss 10 2.582 ± 0.060 s/op
MyBenchmark.case06_WithTieredStopAtLevel1Option ss 10 1.980 ± 0.037 s/op
MyBenchmark.case07_WithSpringConfigLocationOption ss 10 3.026 ± 0.139 s/op
MyBenchmark.case08_WithJmxDisabledOption ss 10 2.877 ± 0.097 s/op
MyBenchmark.case09_WithoutLogback ss 10 2.904 ± 0.096 s/op
MyBenchmark.case10_WithoutJackson ss 10 2.789 ± 0.093 s/op
MyBenchmark.case11_WithoutHibernateValidator ss 10 2.857 ± 0.084 s/op
MyBenchmark.case12_WithAppCds ss 10 2.957 ± 0.079 s/op
MyBenchmark.case13_Exploded ss 10 2.476 ± 0.091 s/op
MyBenchmark.case14_ExplodedWithAppCds ss 10 1.535 ± 0.036 s/op
MyBenchmark.case15_AllApplied ss 10 0.801 ± 0.037 s/op
关于"如何让SpringBoot启动更快一点"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。