你的Spring應用啟動很慢?不妨試試這個工具!

2023-07-24 12:01:39

睡不著閒逛,在GitHub上看到一個挺實用的開源專案:Spring Startup Analyzer

從專案名稱中就大概能猜到,這是一個分析Spring應用啟動過程的工具。Spring Startup Analyzer通過採集Spring應用啟動過程的資料,進而生成一個互動式的分析報告,幫助使用者發現Spring應用啟動慢的位置。

同時,Spring Startup Analyzer還提供了Spring Bean非同步初始化的工具,來幫助開發者加快Spring應用的啟動時間。

下面一起來看看其提供的強大功能。

分析能力

我們可以先從該專案中給出HTML樣例報告來看看它所提供的分析功能。感興趣的可以通過下面連結存取:

把報告內容的細節部分都收起來,可以看到如下圖所示的內容:

主要有六個部分:

  • 啟動的統計資料。其中包括:啟動時間、Bean的數量、使用/總共的JAR包數量、未使用/總共的JAR包數量、ClassLoader數量

  • Spring Bean初始化資料。這裡採集了每個Spring Bean的初始化時間及其細節內容

  • Bean初始化時間線。通過時間線的方式,清晰地展現了Spring應用啟動時候,各個Bean的順序關係以及時間消耗

  • 方法呼叫的詳細資訊。這裡統計了每個方法的呼叫時間、總時間開銷和每次呼叫的平均時間

點開之後,還能看到具體每次呼叫時候的時間開銷和一些呼叫細節:

  • 啟動後未使用的JAR。列出了所有Spring應用啟動後沒有使用的jar包,可以有效的幫助你清理不需要的依賴,為應用瘦身

  • 應用啟動過程的執行緒火焰圖

如何使用

通過上面的介紹,相信你已經瞭解該工具的強大之處了。接下來就可以通過下面的方法嘗試分析一下自己的應用吧:

第一步:從裡面的連結中下載最新的安裝包

https://github.com/linyimin0812/spring-startup-analyzer/tags

第二步:解壓下載的安裝包,記住解壓後的路徑,下面一步要用

第三步:編輯Spring Boot的啟動引數,包括:

  1. 該工具採用agent的方式啟動,所以要新增引數-javaagent:$HOME/spring-startup-analyzer/lib/spring-profiler-agent.jar,這裡$HOME代表以前的解壓路徑,記得根據上面解壓後的路徑編輯這個引數
  2. 設定分析工具的引數,這裡根據自己需要新增即可,比如可以設定超時時間30分鐘:-Dspring-startup-analyzer.app.health.check.timeout=30,其他可設定項如下表,你可以工具自己應用的情況去修改:

第四步:檢視該工具的紀錄檔,可以通過$HOME/spring-startup-analyzer/logs路徑,這裡$HOME代表以前的解壓路徑,紀錄檔檔案的類別為:

  • startup.log: 啟動過程中的紀錄檔
  • transform.log: 被re-transform的類/方法資訊

另外,該工具還支援自定義擴充套件,這裡DD沒試過,就不具體介紹了。感興趣的童鞋可以根據檔案去試試。

啟動優化

這裡提到了一個啟動加速的優化思路,就是把一些耗時的Bean初始化改成非同步就能實現。該專案提供了Bean的非同步初始化工具,也非常好用,只需要下面幾步就能完成。

第一步:引入依賴

<dependency>
    <groupId>io.github.linyimin0812</groupId>
    <artifactId>spring-async-bean-starter</artifactId>
    <version>2.0.2</version>
</dependency>

第二步:設定引數

# 非同步化的Bean可能在Spring Bean初始化順序的末尾,導致非同步優化效果不佳,開啟設定優先載入非同步化的Bean
spring-startup-analyzer.boost.spring.async.bean-priority-load-enable=true
# 指定非同步的Bean名稱
spring-startup-analyzer.boost.spring.async.bean-names=testBean,testComponent
# 執行非同步化Bean初始化方法執行緒池的核心執行緒數
spring-startup-analyzer.boost.spring.async.init-bean-thread-pool-core-size=8
# 執行非同步化Bean初始化方法執行緒池的最大執行緒數
spring-startup-analyzer.boost.spring.async.init-bean-thread-pool-max-size=8

第三步:檢查Bean是否非同步初始化。檢視紀錄檔$HOME/spring-startup-analyzer/logs/startup.log檔案,對於非同步執行初始化的方法,會按照以下格式寫一條紀錄檔:

async-init-bean, beanName: ${beanName}, async init method: ${initMethodName}

但是,作者在檔案中也提到了,非同步並不是萬能的,你還需要注意以下這幾點:

  • 應該優先從程式碼層面優化初始化時間長的Bean,從根本上解決Bean初始化耗時長問題
  • 對於二方包/三方包中初始化耗時長的Bean(無法進行程式碼優化)再考慮Bean的非同步化
  • 對於不被依賴的Bean可以放心進行非同步化,可以通過各個Bean載入耗時中的Root Bean判斷Bean是否被其他Bean依賴
  • 對於被依賴的Bean需要小心分析,在應用啟動過程中不能其他Bean被呼叫,否則可能會存在問題

好了,今天的學習就到這裡!如果您學習過程中如遇困難?可以加入我們超高質量的Spring技術交流群,參與交流與討論,更好的學習與進步!更多Spring Boot教學可以點選直達!,歡迎收藏與轉發支援!

最後,奉上專案地址:https://github.com/linyimin0812/spring-startup-analyzer

歡迎關注我的公眾號:程式猿DD。第一時間瞭解前沿行業訊息、分享深度技術乾貨、獲取優質學習資源