性能優化,簡而言之,就是在不影響系統運行正確性的前提下,使之運行地更快,完成特定功能所需的時間更短。壓測也是檢驗一個架構設計是否合理的一個重要方法。
這個項目是一個線下支付的交易系統,使用線下設備發起支付。項目使用SpringMVC+Dubbo的微服務開發模式,其中SpringMvc做爲Web端部署在tomcat上對外提供rest服務,其餘模塊使用dubbo開發,SpringMVC調用dubbo服務完成業務功能。mysql
這一次的性能優化,目的是在不調整業務邏輯的狀況下經過壓力測試的方式測試下單時接口的性能能達到多少,若是有性能問題,就要在不修改業務邏輯的狀況下經過優化各項參數的方式(包括JVM優化、數據庫鏈接數和Dubbo鏈接數)來提高總體性能。git
壓力測試策略sql
採用按部就班的方式,逐漸增長併發量的方式,先以1個併發開始,慢慢增長,當達到瓶頸的時候就進行參數調整和優化。數據庫
創建壓測分支tomcat
壓測優化過程當中,可能隨時須要調整配置參數,可能會對一些配置參數進行修改或者對公共代碼進行優化。爲了避免讓其餘研發人員的開發受到干擾,在git上基於release分支創建了feature_stress分支,專門用來壓測過程當中,參數配置調優使用,不影響其餘研發人員的開發。性能優化
搭建壓測環境服務器
爲了避免不影響研發和測試人員的工做,單獨申請了三臺4C32G的虛擬機進行壓力測試,一臺部署tomcat,一臺部署dubbo服務,一臺部署mysql。爲何只申請單機部署的方式壓測呢?由於本次測試的目的是看單臺服務器的性能狀況,優化的目的是將單臺服務器的性能最大化。多線程
準備測試腳本架構
本次測試選用jmeter做爲測試工具進行壓力測試,由測試人員模擬線下支付的流程寫好測試腳本。併發
很保守的,從1個併發開始壓測,測試結果讓人很是的驚喜,壓測開始幾分鐘後,就出現大量的鏈接失敗,沒法繼續測試。出現大量的內存溢出的異常。沒出現異常時的吞吐量達到了1req/s。同時,經過jconsole控制檯監控tomcat,發現其線程數最高到了2萬多個。
問題分析
這個異常是建立本地線程失敗拋出的異常,爲何有這麼大量的線程呢?不合常理呀!因而查看對應的代碼,原來這是一個自定義的一我的日誌Appender,在這個Appender裏使用了線程池,這個Appender原本的目的是使用多線程提高日誌性能,而且將全部的日誌都收集到一個文件中。代碼相似以下:
log4j.properties中直接將新的Appender添加到了rootLogger下:
經過以上代碼和日誌配置文件就能看出來,每第二天志輸出都會建立線程,這就是線程爲何愈來愈多,最後致使沒法建立新的本地線程的緣由。
爲了避免影響現有的功能,將LogAppender類append方法中的線程池建立的部分變成了類的屬性,並固定只用8個線程:
提交代碼從新部署壓測環境,再進行壓測,吞吐量立刻就上來了,達到了1700req/s,
][7]
通過上面的優化以後,總體的性能還不是很高,通過jconsole監控發現,線程數仍是很高,雖然沒有2萬那麼多了,但仍是有3000多的線程,這麼多的線程根本沒法發揮機器的性能,時間都浪費在線程切換上了,經過查看線程棧發現大量的線程都是dubbo鏈接的線程,爲何如此之多呢?查看dubbo的配置文件,consumer的連接數都設置成了1000,因而將全部dubbo的consumer鏈接數均改成了64。同時將log4j.properties中配置了控制檯輸出的都關閉了。
最終的優化後的測試結果,最高達到了2600req/s。
性能優化須要從幾個方面考慮:
———— / END / ————