總結:測試——分析——優化
一、測試--> 輸出,性能測試報告
1、微基準性能測試
精準測試,測試某個模塊/方法在不同的實現方式下的性能表現。
2、宏基準性能測試,
綜合測試,考慮:測試環境、場景、目標
環境,模擬真實線上環境
場景,排除干擾因素,包含:其他服務、第三方接口
目標,逐漸增加併發數,測試TPS(最大的每秒事務請求數),並觀察:吞吐量、響應時間、cpu、內存、磁盤IO、網絡IO使用率等
輸出“性能測試報告”,包含以下指標:
測試接口的平均/最大/最小吞吐量
響應時間
cpu/內存/磁盤IO/網絡IO的資源使用率
jvm的gc頻率
干擾因子
1、熱身問題
現象,第一次請求接口比較慢,後面請求越來越快
分析,.java文件被編譯爲.class文件後,需要解釋器轉化爲機器碼 才能運行。某個方法/代碼塊被經常執行,則被虛擬機認定爲“熱點代碼”。爲了提高執行效率,虛擬機通過編譯器把這些代碼編譯爲與本地平臺相關的機器碼,並進行各個層次的優化,後存儲在內存中,之後運行時,直接從內存中獲取。因此,剛開始運行時比較慢(虛擬機花長時間全面優化代碼),越往後越快
2、測試結果不穩定
即使測試的數據集一樣,結果也可能有差異。考慮,機器中其他進程影響,網絡波動,jvm垃圾回收等
可以通過多次測試,求平均值/統計曲線圖,保證平均值在合理範圍之內即可。
3、多jvm的影響
任意一個jvm都擁有整個系統的資源使用權,儘量保證線上環境一臺機器中部署一個jvm。
二、分析 (自下而上)
按照下面順序,分析“性能測試報告”
1、計算機資源:cpu、內存、磁盤IO、網絡IO 是否存異常?並查看異常日誌
2、容器:web容器
3、jvm層面:垃圾回收頻率、內存分配情況
4、應用服務器:java編碼問題、讀寫數據瓶頸
三、優化(自上而下)
1、應用層的調優
1)優化代碼,因爲資源耗盡而暴露。
代碼問題,如:內存溢出/jvm內存用完,引發jvm頻繁垃圾回收,導致cpu1000%,又消耗系統cpu資源
非代碼問題,如:for循環遍歷LinkedList。每次循環都要遍歷一次鏈表,降低讀的效率。
2)優化設計,利用設計模式優化業務層/中間層的代碼設計,精簡代碼,提高性能
如,單例模式,共享創建的兌現,減少頻繁創建、銷燬帶來的性能消耗
3)優化算法
如,查找算法
4)時間換空間,適用於對存儲容量要求苛刻,單查詢速度不作要求的場景
如,String的interm方法,將重複率高的數據存儲在常量池中,節省存儲空間。(常量池使用HashMap實現,不能存儲過多數據,否則性能下降)
5)空間換時間,提升訪問速度
如,分庫分表。mysql單表數據上千萬時,讀寫性能明顯下降。
2、系統調優
1)jvm調優,合理設置jvm內存空間、垃圾回收策略
若業務中創建大量的大對象,可以通過設置將大對象直接放入 老年代,減少年輕代頻繁發生小的垃圾回收(minor gc),減少cpu佔用時間
2)組件調優
如,web容器,線程池的設置
3)操作系統調優,優化內核參數
四、兜底策略!
無論系統調優多麼好,總會存在承受極限,通過兜底方法,保證系統穩定性。
1、限流熔斷。設置最大訪問限制(參考tps值),友好返回沒有成功的請求。
2、擴容
1)智能橫向擴容。當訪問量超過指定閾值,自動新增/減少機器。
2)提前擴容。常用於 高併發系統。
如,瞬間的搶購業務,要提前加機器;瞬間大量請求,即使橫向擴容成功了,搶購也結束了。
推薦,Kubernetes作爲Docker容器的容器管理器,可以實現智能 橫向擴容+ 提前擴容Docker服務
總結,
任何調優都需要結合場景,明確已知問題和性能目標,不能爲了調優而調優,否則帶來風險和bug。
調優策略千變萬化,但思想和核心都一樣的。都是從業務調優——編碼調優——系統調優