加快Spring Boot啟動的幾種方法 | baeldung
在本教程中,我們將介紹有助於減少 Spring Boot 啟動時間的不同配置和設定:
- 首先,我們將討論 Spring 特定的配置。
- 其次,我們將介紹 Java 虛擬機器選項。
- 最後,我們將介紹如何利用 GraalVM 和本機映象編譯來進一步縮短啟動時間。
延遲初始化
Spring Framework 支援延遲初始化。延遲初始化意味著 Spring 不會在啟動時建立所有 bean。此外,在需要該 bean 之前,Spring 不會注入任何依賴項。從 Spring Boot 2.2 版開始。可以使用application.properties啟用延遲初始化:
spring.main.lazy-initialization=true
根據我們程式碼庫的大小情況,延遲初始化甚至會導致很大的啟動時間減少。這種減少取決於我們應用程式的依賴關係圖。
此外,延遲初始化在使用 DevTools 熱重啟功能的開發過程中也有好處。使用延遲初始化增加重啟次數將使 JVM 能夠更好地最佳化程式碼。
但是,延遲初始化有一些缺點。最顯著的缺點是應用程式會較慢地處理第一個請求。因為 Spring 需要時間來初始化所需的 bean,另一個缺點是我們可能會在啟動時遺漏一些錯誤。這可能會在執行時導致ClassNotFoundException 。
排除不必要的自動配置
Spring Boot 總是喜歡約定而不是配置。Spring 可能會初始化我們的應用程式不需要的 bean。我們可以使用啟動日誌檢查所有自動配置的 bean。在application.properties 中的org.springframework.boot.autoconfigure上將日誌記錄級別設定為 DEBUG :
logging.level.org.springframework.boot.autoconfigure=DEBUG
在日誌中,我們將看到專用於自動配置的新行,然後根據這些輸出,我們可以排除這些應用程式配置。
為了排除部分配置,我們使用@EnableAutoConfiguration註解:
@EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class, JvmMetricsAutoConfiguration.class, LogbackMetricsAutoConfiguration.class, MetricsAutoConfiguration.class}) |
如果我們排除 Jackson JSON 庫和一些我們不使用的指標配置,我們可以在啟動時節省一些時間。
切換到 Undertow
Spring Boot 帶有一個嵌入式 servlet 容器。預設情況下,我們得到 Tomcat。雖然 Tomcat 在大多數情況下已經足夠好,但其他 servlet 容器的效能可能更高。在測試中,來自 JBoss 的 Undertow 的效能優於 Tomcat 或 Jetty。它需要更少的記憶體並具有更好的平均響應時間。要切換到 Undertow,我們需要更改pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> |
生成索引
Spring 類路徑掃描是快速操作。當我們擁有大型程式碼庫時,我們可以透過建立靜態索引來縮短啟動時間。我們需要給spring-context-indexer新增一個依賴來生成索引。Spring 不需要任何額外的配置。在編譯時,Spring 將在META-INF\spring.components 中建立一個附加檔案。Spring 會在啟動時自動使用它:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-indexer</artifactId> <version>${spring.version}</version> <optional>true</optional> </dependency> |
搜尋多個位置
application.properties(或 .yml)檔案有幾個有效的位置。最常見的是在類路徑根目錄或與 jar 檔案相同的資料夾中。我們可以透過使用spring.config.location引數設定顯式路徑來避免搜尋多個位置,並在搜尋時節省幾毫秒:
java -jar .\target\springStartupApp.jar --spring.config.location=classpath:/application.properties |
最後,Spring Boot 提供了一些 MBean 來使用 JMX 監控我們的應用程式。完全關閉 JMX 並避免建立這些 bean 的成本:
spring.jmx.enabled=false
JVM的Verify調整
此標誌設定位元組碼驗證器模式。位元組碼驗證提供類的格式是否正確以及是否在 JVM 規範約束內。我們在啟動期間在 JVM 上設定了這個標誌。
Verify標誌有幾個選項:
- -Xverify是預設值並啟用對所有非引導載入程式類的驗證。
- -Xverify:all啟用對所有類的驗證。此設定將對初創公司產生顯著的負面效能影響。
- -Xverify:none(或-Xnoverify)。此選項將完全禁用驗證程式並將顯著減少啟動時間。
我們可以在啟動時傳遞這個標誌:
java -jar -noverify .\target\springStartupApp.jar |
我們將收到來自 JVM 的警告,指出該選項已被棄用。但是啟動時間減少了。
這個標誌帶來了重要的權衡。我們的應用程式可能會在執行時因我們可以更早捕獲的錯誤而中斷。這是該選項在 Java 13 中被標記為已棄用的原因之一。因此它將在未來版本中刪除。
JVM分層編譯標誌
Java 7 引入了分層編譯。HotSpot 編譯器將對程式碼使用不同級別的編譯。
眾所周知,Java 程式碼首先被解釋為位元組碼。接下來,位元組碼被編譯成機器碼。這種轉換髮生在方法級別。C1 編譯器在一定數量的呼叫後編譯一個方法。執行更多次之後,C2 編譯器會編譯它,從而進一步提高效能。
使用-XX:-TieredCompilation標誌,我們可以禁用中間編譯層。這意味著我們的方法將使用 C2 編譯器進行解釋或編譯,以實現最大程度的最佳化。這不會導致啟動速度下降。我們需要的是禁用 C2 編譯。我們可以使用-XX:TieredStopAtLevel=1選項來做到這一點。結合-noverify標誌,這可以減少啟動時間。不幸的是,這會在後期減慢 JIT 編譯器的速度。
Spring Native
本機映像/映象(Image)是使用提前編譯器編譯並打包成可執行檔案的 Java 程式碼。它不需要Java來執行。由於沒有 JVM 開銷,因此生成的程式速度更快,對記憶體的依賴更少。該GraalVM專案介紹本機映像和所需的構建工具。
Spring Native是一個實驗性模組,支援使用 GraalVM 原生映象編譯器對 Spring 應用程式進行原生編譯。提前編譯器在構建期間執行多項任務以減少啟動時間(靜態分析、刪除未使用的程式碼、建立固定類路徑等)。原生映象仍然有一些限制:
- 它不支援所有 Java 功能
- 反射需要特殊的配置
- 懶載入類不可用
- Windows 相容性是一個問題。
要將應用程式編譯為原生映像,我們需要將spring-aot 和spring-aot-maven-plugin依賴項新增到pom.xml。Maven 將在目標資料夾中的package命令上建立本機映像。
相關文章
- Spring Boot幾種啟動問題的解決方案Spring Boot
- 基於Spring Batch的Spring Boot的教程 - BaeldungBATSpring Boot
- Spring Boot Reactor Netty配置 | BaeldungSpring BootReactNetty
- 盤點 Spring Boot 解決跨域請求的幾種方法Spring Boot跨域
- Spring Boot面試問題| BaeldungSpring Boot面試
- Spring Boot微服務中的十二因子方法論(12Factor) - BaeldungSpring Boot微服務
- Spring Boot開啟的2種方式Spring Boot
- 在Spring Boot設定Swagger 2 - BaeldungSpring BootSwagger
- GraphQL SPQR和Spring Boot入門 | baeldungSpring Boot
- Java中實現執行緒安全HashSet的幾種方法 | baeldungJava執行緒
- spring-boot啟動Springboot
- Spring Boot啟動流程Spring Boot
- Spring Boot讀取配置檔案的幾種方式Spring Boot
- Spring Boot的Clean架構教程與原始碼 - BaeldungSpring Boot架構原始碼
- ubuntu下圖形程式自啟動的幾種方法Ubuntu
- Spring Boot Starters啟動器Spring Boot
- Spring Boot Runner啟動器Spring Boot
- Spring Boot 啟動過程Spring Boot
- Spring Boot中初始化資源的幾種方式Spring Boot
- Spring Boot 切面的一種的測試方法Spring Boot
- Spring Boot啟動流程簡述Spring Boot
- Maven專案Spring Boot啟動MavenSpring Boot
- spring-boot-route(一)Controller接收引數的幾種方式SpringbootController
- 你應該知道的幾種Spring boot非同步呼叫方式Spring Boot非同步
- Spring Boot專案的推薦軟體包結構 - BaeldungSpring Boot
- 使用Spring Boot排程WebSocket推送的教程和原始碼 - BaeldungSpring BootWeb原始碼
- 如何讓spring boot 啟動後就執行某個方法Spring Boot
- 幾種集合的幾種方法
- 延緩Spring Boot啟動時間直到資料庫啟動的方法和原始碼 - MartenSpring Boot資料庫原始碼
- Spring Boot(三):Spring Boot中的事件的使用 與Spring Boot啟動流程(Event 事件 和 Listeners監聽器)Spring Boot事件
- spring-boot-route(二)讀取配置檔案的幾種方式Springboot
- 在Spring Boot中建立自己的啟動器Spring Boot
- Spring Boot中Tomcat是怎麼啟動的Spring BootTomcat
- Spring Boot定製啟動圖案Spring Boot
- 幾種有效的清除浮動的方法
- [maven][spring boot] mvn spring-boot:run啟動時,指定pom檔案MavenSpring Boot
- 11個點讓你的Spring Boot啟動更快Spring Boot
- Spring Boot(三):RestTemplate提交表單資料的三種方法Spring BootREST