天天看點

系統啟動慢,調優後我直呼Nice

作者:馬士兵教育CTO
系統啟動慢,調優後我直呼Nice

問題背景

最近在負責一個訂單系統的業務研發,本來不是件困難的事。但是服務的啟動時間很慢,慢的令人發指。單次啟動的時間約在10多分鐘左右,基本一次疊代、開發,大部分的時間都花在了啟動項目上。忍無可忍的我,終于決定找到啟動慢的原因。

方案探索

起初對于優化項目啟動速度,是毫無頭緒。也是傻傻的從百度上去搜解決的方案。一下子就搜到了Jprofiler這個軟體,據說是能快速找到錯誤棧的位置。但是不得不說這軟體真的很坑,不僅收費(MAC破解巨難找,找到了還打不開),而且實際因為很多Spring類都是采用動态代理加載的,Jprofiler根本判斷不出來錯誤位置在哪。

嘗試Jprofiler無果後,從網上還看到了一個另外的方法,可以通過對運作中的線程作快照,來定位是否存在有死循環的線程。進而優化啟動速度。

系統啟動慢,調優後我直呼Nice

采用Thread dump的方式,比較适合你清楚大緻原因的時候使用,否則你盲目的去截取到的線程,實際上也很難定位是不是目前線程的問題。盡管錯誤棧很全,但意味着你需要了解的源碼更深。對我這種小白,依舊很難get到具體的原因。

深入鑽研

采用網上的解決方案都無疾而終後,決定還是采用最笨的方法解決,就一點點的debug吧!于是在SpringBoot的啟動類org.springframework.boot.SpringApplication#run上打滿了debug點,逐個關鍵的debug點去調試。

系統啟動慢,調優後我直呼Nice

盡管方案很笨也很耗時,啟動一次基本10分鐘左右。但是很快定位到了啟動緩慢的原因。在Springboot的BEAN後處理器的加載方法中,有一個關鍵的Bean容器DSLContext啟動極其的慢,大概需要6、7分鐘左右。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

系統啟動慢,調優後我直呼Nice

然而,dslContext是個啥玩意,他為啥又讓我的系統啟動慢了呢?

系統啟動慢,調優後我直呼Nice

文章裡寫到,dslContext啟動慢的原因主要是有個:AnnotationAwareAspectJAutoProxyCreator的處理器,該處理器會掃描dslContext中的方法,并逐一判斷目前的方式是否需要動态代理。dslContext中包含約800+的方法啟動自然會很慢。

最終解決

知道了原因,那麼自然也就知道了解決方案。隻要讓Springboot不掃描到這個dslContext元件了,那麼就可以加快啟動速度了不是?那麼自然就可以從兩個角度出發:

1、修改Springboot的掃描範圍,不掃描即可;

2、不導入dslContext的依賴包,讓Springboot掃描不到

我首先嘗試了第一種方法,修改了啟動類上 @ComponentScan和 @EnableFeignClients的兩個注解的掃描範圍,然而,無論我怎麼修改,實際上都沒有生效。(大機率猜測是因為dslContext并不是采用@Componet注解的方式而是采用@Configuration注入的方式導緻。)

無奈之下,隻能按照第二種思路去考慮解決方案。然而,作為一個飽經風霜的項目,maven依賴多到數不清,根本不知道該從何下手。

嘗試通過Maven Helper插件去搜尋dslContext的maven依賴,卻也是毫無作用。

(PS:這裡不得不提一下Maven Helper這個插件,這個插件可以很快找到我們所依賴的maven,是我平日用來排除相關依賴的利器。)

系統啟動慢,調優後我直呼Nice
系統啟動慢,調優後我直呼Nice

也就是抱着嘗試的心态,在百度下搜尋了一下“使用dslContext”的關鍵字,很幸運的是,在第二個搜尋位置跳出了jooq這個名詞。

系統啟動慢,調優後我直呼Nice

于是懷疑,是不是這個jooq依賴把dslContext導入進來了呢?嘗試着一搜,果然!

系統啟動慢,調優後我直呼Nice

毫不猶豫點選了exclude,再啟動一次。問題解決!

經驗總結

解決項目啟動慢的原因其實是個很依靠個人經驗和運氣、玄學的過程,但是還是有一些方法有迹可循。

1、可以考慮Jprofiler去記錄線程的啟動時間。(但本次效果不佳,可能需要更正常的打開方式)

2、可以考慮采用截取線程快照的方式定位。

3、最最笨的方法就是采用Debug的方式定位。

在定位到具體的啟動緩慢的原因後,如果是因為注入的問題,有下面兩條解決思路:

1、不掃描對應的Component元件,可以通過修改@Component、@EnableFeignClients的basePackge參數來控制。

2、如果上述的參數沒有生效,可以考慮嘗試百度定位引入這個元件的maven依賴是什麼,并借助Maven Helper插件将該依賴排除。

繼續閱讀