javascript
Spring Boot 启动,1 秒搞定!
原文:?dev.to?翻譯:?ImportNew.com?-?唐尤華
譯文:?http://www.importnew.com/30647.html
“Spring有多快?”
這是?2018?Spring?One?Platform?中的一場會(huì)議。看完會(huì)議視頻,我自己動(dòng)手試了一下。下面是我做出的測試結(jié)果。
還沒有觀看視頻的朋友推薦看一下,非常有意思。
https://springoneplatform.io/2018/sessions/how-fast-is-spring-
本文使用的代碼
https://github.com/bufferings/spring-boot-startup-mybench
↓我使用的是?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)
可以按照下面這樣運(yùn)行基準(zhǔn)測試。運(yùn)行起來可能需要一些時(shí)間,下面會(huì)執(zhí)行所有的測試。
? ./mvnw clean package
? (cd benchmarks/; java -jar target/benchmarks.jar)
1. FluxBaseline
我使用?SpringInitializr?創(chuàng)建項(xiàng)目,僅包含?Reactive?Web。接下來,我會(huì)寫一個(gè)?WebMVC?風(fēng)格的極簡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。
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.0.RELEASE</version><relativePath/>?<!--?lookup?parent?from?repository?--> </parent>啟動(dòng)結(jié)果?2.938?±?0.287?s/op
Benchmark? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Mode? Cnt? Score? ?Error? Units
MyBenchmark.case01_FluxBaseline? ? ? ? ? ? ? ? ? ? ? ss? ?10? 2.938 ± 0.287? ?s/op
現(xiàn)在,以這個(gè)結(jié)果作為基線。讓我們從這里開始。
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?快了一點(diǎn),難道不是嗎?
3. spring-context-indexer
接下來,我試了?spring-context-indexer,似乎創(chuàng)建了?component?index。
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-indexer</artifactId><optional>true</optional> </dependency>嗯…慢了一點(diǎn)點(diǎn)?
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,發(fā)現(xiàn)只包含了一個(gè)組件。了解...我應(yīng)該嘗試更大一點(diǎn)的項(xiàng)目,這樣才能看到效果。
#
#Sun?Nov?04?18:42:59?JST?2018
com.example.DemoApplication=org.springframework.stereotype.Component
4. 惰性初始化
嘗試了惰性初始化。Spring Boot 2.2 增加了一個(gè)新功能,啟動(dòng)飛起,大家可以看下這篇文章,馬上就要上市了。?
@Configuration public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {for?(String?beanName?:?beanFactory.getBeanDefinitionNames())?{beanFactory.getBeanDefinition(beanName).setLazyInit(true);}}}查看結(jié)果,啟動(dòng)變快了一點(diǎn)。
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
運(yùn)行加?-noverify?選項(xiàng):
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
啟動(dòng)變得快了一點(diǎn)。不知道為什么有這個(gè)結(jié)果,稍后需要仔細(xì)了解一下。
6. TieredStopAtLevel
運(yùn)行加?-XX:TieredStopAtLevel=1?選項(xiàng):
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秒。還是不知道這個(gè)參數(shù)有什么含義,稍后需要仔細(xì)了解一下。
7. 指定 SpringConfigLocation 參數(shù)
運(yùn)行加?-Dspring.config.location=classpath:/application.properties?選項(xiàng):
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. 關(guān)閉 JMX
運(yùn)行加?-Dspring.jmx.enabled=false?選項(xiàng):
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
變得快了一點(diǎn)。
9. 取消 Logback
從這里開始,我開始減少函數(shù)庫。開始,取消?Logback:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId><exclusions><exclusion><artifactId>spring-boot-starter-logging</artifactId><groupId>org.springframework.boot</groupId></exclusion></exclusions> </dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-jdk14</artifactId> </dependency>結(jié)果如下:
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
嗯…似乎有一點(diǎn)點(diǎn)改進(jìn)?
10. 取消 Jackson
接下來是 Jackson
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId><exclusions><exclusion><artifactId>spring-boot-starter-json</artifactId><groupId>org.springframework.boot</groupId></exclusion></exclusions> </dependency>結(jié)果如下:
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
結(jié)果變快了一點(diǎn)。
11. 取消 HibernateValidator
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId><exclusions><exclusion><artifactId>hibernate-validator</artifactId><groupId>org.hibernate.validator</groupId></exclusion></exclusions> </dependency>結(jié)果如下:
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
也有一點(diǎn)效果。
到這里為止,不再取消函數(shù)庫了。
12. AppCDS
AppCDS?(Application?Class?Data?Sharing)?是?Oracle?JDK?的一個(gè)企業(yè)版功能。OpenJDK?10?開始包含了這個(gè)功能。
看起來?AppCDS?轉(zhuǎn)儲信息存到了一個(gè)共享壓縮文件,所以啟動(dòng)時(shí)間變短了。
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的相關(guān)文章,找到原因了。
SpringBoot?FatJAR?不在?CDS?管理范圍內(nèi)。
13. 使用 Thin Launcher 的 Flux
嗯,對不起,“Exploded”?基準(zhǔn)測試錯(cuò)了。我曾經(jīng)試著使用?FatJAR,但是?CDS?不能這么干。所以,我轉(zhuǎn)而使用?Thin?Launcher,所以?“Exploded”?就變成了?“Thin?Launche”。
使用?CDS?以前,我會(huì)測試使用?Thin?Launcher?打包?JAR?文件的啟動(dòng)速度。
<plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><dependencies><dependency><groupId>org.springframework.boot.experimental</groupId><artifactId>spring-boot-thin-layout</artifactId><version>1.0.15.RELEASE</version></dependency></dependencies></plugin> </plugins>盡管我使用?Thin?Launcher?打包?app,但并沒有使用?Thin?Launcher?啟動(dòng)類,而是使用?Main?class?讓啟動(dòng)盡可能快一些。
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
嗯,快了一點(diǎn),對嗎?
14. Thin Launcher + CDS
現(xiàn)在,我要使用?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. 所有操作都上
最終,我把所有操作都用上。
Benchmark? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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秒鐘!(∩′?`)∩耶
更進(jìn)一步
在?Dave?的視頻中,他提到了“函數(shù)式?Bean?定義”,嘗試僅使用?Spring?不用?Spring?Boot,app變得更快了。其中的道理還需要進(jìn)一步了解。
結(jié)果:
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
真的很有意思。感謝!
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的Spring Boot 启动,1 秒搞定!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于 HTTP 协议的 3 种实时数据获
- 下一篇: 我建议你了解一点儿Serverless