前言
公司打算舉辦一場活動,現場參與活動人數比較多。針對於可能訪問比較密集的接口進行壓力測試。使用jmeter進行測試,請求並發稍微多些,系統就會掛起。
針對壓力測試出現的問題,因為並發超過1秒鍾100筆就會出現問題,Spring Cloud作為一個成熟的框架,不可能是框架不支持。所以首先想到的是配置上需要進行調優。
1、Spring Cloud配置調優
請求從jmeter發出后,需要通過Zuul網關,然后到Spring Cloud微服務端。所以,整個調優方向分為兩個地方:微服務端和zuul網關。
1.2、微服務應用
當jmeter調整到每秒鍾70個並發請求時,服務應用端的日志中出現了很多hystrix回滾,並且有很多HystrixRuntimeException。
com.netflix.hystrix.exception.HystrixRuntimeException ... could not be queued for execution...
原因:Hystrix請求線程池缺省為最大10個線程,在大量請求下,很容易超過這個數值,導致拋出異常。
解決方法:在配置文件中修改線程池中的coreSize(properties方式的配置文件)
hystrix.threadpool.default.coreSize=500
配置上測試后,客戶端不再出現hystrix的異常了,但是並發請求數進一步提高到100以上后,依然會無法響應請求。
1.3、zuul網關
由於網關也配置使用了Hystrix,在並發請求過大時,也會拋出異常:
com.netflix.hystrix.exception.HystrixRuntimeException: ggx-test short-circuited and no fallback available
顯示的異常時,具體的ggx-test服務系統短路並且沒有熔斷可用,但ggx-test系統還正在運行,所以問題出現在zuul網關上。
① zuul內部路由可以理解為使用一個線程池去發送路由請求,所以我們也需要擴大這個線程池的容量。
zuul.host.maxTotalConnections=1000
zuul.host.maxPerRouteConnections=1000
② zuul使用Hystrix,而Hystrix有隔離策略: THREAD 以及 SEMAPHORE ,默認是 SEMAPHORE ,默認大小是100。請求的並發線程超過100就會報錯。
zuul.semaphore.max-semaphores=5000
配置完上述配置后,重新進行測試,在日志中不會出現錯誤了,但是並發請求超過100/S時,系統掛起,不再響應請求。於是,排查各種可能后,想到了可能是數據庫連接池的問題。
2、數據庫連接池
我們系統使用數據庫連接池是c3p0,最大的數據庫配置的連接數為30個,嘗試將數據庫最大連接數修改到100時,使用jmeter測試,並發請求能夠稍微提高些。這樣能夠定位到問題就在數據庫連接池上。
目前市場上主流的開源數據庫連接池有:C3P0,DBCP,Druid,HikariCp。其中C3P0和DBCP是出現的比較早的數據庫連接,比較穩定,在低並發的情況下,整體表現還不錯,但是在高並發下,響應時間變長,性能很差,甚至於死鎖。Druid是阿里巴巴開源的高性能數據庫連接池,雖然性能不及HikariCp,但是它提供的各種維度的統計分析的功能,在國內市場流行度很高。
相關的數據庫連接池對比:
|
C3P0/DBCP |
Druid |
hikariCP |
應用 |
主要在Hibernate |
各大主流平台 |
起源於boneCP |
性能 |
較差 |
強 |
很強 |
線程池容器 |
Blocking Queue |
List Reentrantlock |
|
綜合,Druid性能比較優異,網上文檔資料很健全,加上可視化的統計分析很適合我們解決當前問題。我們將數據庫連接池從C3P0換到了Druid。
3、總結
經過上面優化,壓力測試達到了預期,jmeter每秒鍾發送1000個並發請求,系統能夠在預期時間內順利返回響應結果。雖然不是很高,但是應對我們當前業務需求是足夠的。沒有最優的架構,只有最合適的架構,一切系統設計原則都要以解決業務問題為最終目標,脫離實際業務的技術情懷架構往往會給系統帶入大坑。當然這並不能影響我們對技術的追求,在碰到並發請求大的情況下,有幾個維度可以進行嘗試優化:首先就是限流,將請求攔截下來,不要對系統造成太大壓力;其次使用各種緩存,對於不需要訪問數據庫的資源緩存起來,提高響應速度,減少數據庫壓力;然后使用分布式部署,使用集群替代單機;還有優化接口對SQL進行調優等等。