讓Spring Boot啟動更快


關注公眾號:鍋外的大佬, 每日推送國外技術好文,幫助每位開發者更好成長

原文鏈接:https://dev.to/bufferings/lets-make-springboot-app-start-faster-k9m

作者:Mitz

譯者:Lensen

"Spring有多快?" 這是2018年”Spring One Platfrom“大會的一個主題,我看了視頻並親自嘗試了一下。所以我將在這篇文章中,介紹下我所做的事情以及結果。

沒看過的推薦去看一下,蠻有意思的:
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) 

你可以像下面一樣運行基准測試,這需要點時間,因為會執行所有基准測試。

❯ ./mvnw clean package ❯ (cd benchmarks/; java -jar target/benchmarks.jar) 

1.Flux Baseline

我用SpringInitializer創建一個只有Reactive Web的項目,然后用SpringMVC風格創建了一個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.0RELEASE.

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> 

啟動時間為2.938±0.287 s/op。

Benchmark                                          Mode  Cnt  Score   Error  Units
MyBenchmark.case01_FluxBaseline                      ss   10 2.938 ± 0.287 s/op 

現在我得到一個對比啟動時間的基線(baseline),讓我們從這里開始。

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,它似乎創建了主鍵索引

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-indexer</artifactId> <optional>true</optional> </dependency> 

呃...變慢了一點?

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.Lazy Initialization

嘗試懶初始化

@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.No Verify

啟動時使用-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 

Uh!快了很多,啟動時間接近兩秒,但我還是不清楚為什么,稍后我會去查一下。

7.顯式指定SpringConfigLocation

啟動時使用Dspring.config.location=classpath:/application.properties:

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

<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> 

結果如下:

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:

<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> 

看結果:

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

  <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>

結果:

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的相關資料發現:使用Spring Boot FatJAR時,這些庫不在CDS的范圍內。

13.Flux with Thin Launcher

抱歉,基准命名為‘Exploded’是不對的,一次我嘗試暴露FatJar,但我仍然不能使用CDS。所以我現在使用Thin Launcher,所以請把基准名稱從Exploded改為Thin Launcher吧。

在使用CDS之前,我想檢查下使用Thin Launcher打包的速度。

 <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的啟動類,而是指定了Main類來讓啟動時間盡可能快些。

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 

Wow! 它變快了很多!

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秒鍾!yeah!

16.還有一點

在Dave的會議上,他提到了“函數Bean定義”(Functional Bean Definitions),嘗試在沒有SpringBoot的情況下使用Spring進行改進,應用程序變得更快了。我需要學習更多來理解他們。

17.結果列表

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 

感謝觀看!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM