大家先來看下面兩張圖,一樣的接口,查詢時間波動很大:
這個問題糾纏很久了,之前我做btr-open-web開放平臺的時候就有遇到,後面想去查一下,但是後面開放平臺沒人用,就沒動力去處理了。接着btr-srm-web也有這個問題,當時吳通大佬沒找出來,我看到跟我之前遇到的一樣。然後測試跟產品也反饋大概半年了,之前查了一下,沒查到放棄了,也都能湊合用,一會纔會慢一下,內部用,也一直沒處理,拖到現在。
思考:偶爾查詢慢的問題,一開始懷疑的連接池的問題,獲取連接慢,慢慢加大最小連接數,也還是不行。
最後爲了驗證是不是連接池的問題,我把最小、最大、初始化設置成一樣。然後發現還是一樣,想想也沒道理,新建連接怎麼也不用10幾秒。
實在沒辦法了,把接口時間打印出來,把所有日誌改成debug,下面的圖就是我截取的有問題的部分。找到時間長的,原來發現了不知道爲啥要加載類,要查找類。以爲是BeanUtils工具類的問題,然後我去掉了,然後繼續請求,還是有慢的。
然後我又去看日誌(下圖),發現沒有使用這個。然後再看,有點奇怪,看起來要重新classload類進去?這時候不懂了,按道理不是一開始加載進去了嗎?
就去谷歌一下。因爲我發現兩個項目都是spingboot,我猜是它,所以搜了spingboot+findClass ClassNotFoundException,沒想到還真的搜到了。有個人遇到jsp的問題,然後也是打包成war(我們公司的springboot也都是打包成war)包,然後也是找不到類,也是慢,我就看了一下,下面去這個文章的截圖。
裏面有springboot項目的一個issues,講的就是類加載慢的問題,後面這個是springboot成員給的方案,剛好直接用,很好的解決了,我截一下主要的給大家看看
具體原因(暫無一步一步跟蹤源碼,看兩種解決方案總結出來):
根據上面的上的討論,因爲embeded tomcat默認會開啓reloadable熱加載,默認每超過15秒都會嘗試重新加載。這也大概解釋了爲什麼日誌顯示加載不到還是能正常跑,估計首次啓動的時候是通過spring boot的類加載成功了,後面對於war包,springboot找資源的時候,應該是沒考慮這樣的情況,tomcat的熱加載不支持的兩層嵌套就會一直失敗,然後導致加載慢。
具體大家可以直接看看兩種解決方案,裏面有詳細對話信息,鏈接我發出來了。
問題處理:
springboot 1.0解決方案:不允許自動重新load類,按道理也沒必要。
springboot 2.0解決方案:直接重寫查找lib的方法,兼容springboot打包成war的情況,建議第二種。
https://github.com/spring-projects/spring-boot/issues/16471
因爲我們是springboot 2.x,所以我直接使用方案2,然後點了好久,都沒有慢的,沒有發現這個問題了。大家可以去新商家平臺操作一下,除了33環境(我發了我的分支),其它分支之前的都是時不時會有接口10秒左右。
http://docker33-srm.qipeipu.net/#/,http://docker34-srm.qipeipu.net/#/,可以對比一下這兩個環境,大家去多點點就發現了。
總體思路:
第一個方案是不給tomcat自動加載,把參數設置爲false
第二是springboot做了擴展,支持了war資源問題的加載,然後就正常使用了。
下面就是擴展類,加強了war的資源lib的處理。