天天看點

Java性能調優實戰-如何制定性能調優政策?                                    如何制定性能調優政策?

                                    如何制定性能調優政策?

1.性能測試攻略

1.1.微基準性能測試

微基準性能測試可以精準定位到某個子產品或者某個方法的性能問題。

1.2.宏基準性能測試

宏基準性能測試是一個綜合測試,需要考慮到測試環境、場景和目标。

2.性能測試需要注意的問題

2.1.熱身問題

做性能測試時,系統會運作得越來越快,是為什麼呢?

在java環境中,.java檔案編譯成為.class檔案後,機器還是無法執行的,需要通過解釋器将位元組碼轉成機器碼才能執行。最初執行時的代碼會被解釋器先解釋執行。代碼執行次數較多時,虛拟機會将這些代碼認定為熱點代碼(Hot Spot Code),為了提高效率,虛拟機将會通過及時編譯器(JIT compiler, just-in-time compiler)把這些代碼編譯成與本地平台相關的機器碼,并進行優化,然後存儲在記憶體中,之後運作這些代碼是,直接從記憶體中擷取即可。

是以在剛開始運作的階段,虛拟機會花費很長的時間來全面優化代碼,後面就能以最高的性能執行了。這就是熱身過程,如果在進行性能測試時,熱身時間過長,就會導緻第一次通路速度過慢,就要考慮先優化再測試了。

2.2.性能測試結果不穩定

做性能測試時每次的結果都有差異,可以采用多次測試求平均值,保證平均值在合理範圍内。

2.3.多jvm情況的影響

如果多個java應用服務部署在不同的tomcat下,就會有多個jvm,任意一個jvm都擁有整個系統的資源使用權。如果一台伺服器隻部署一個jvm,性能測試結果很好,但在一台伺服器上部署多個jvm情況就不一定了,是以盡量避免線上環境中一台伺服器部署多個jvm的情況。

3.合理分析結果,制定調優政策

完成性能測試之後,需要輸出一份性能測試報告,幫我們分析系統性能測試的情況。其中測試結果需要包含測試接口的平均、最大和最小吞吐量,響應時間,伺服器的 CPU、記憶體、I/O、網絡 IO使用率,JVM 的 GC 頻率等。

通過觀察這些調優标準,可以發現性能瓶頸,我們再通過自下而上的方式分析查找問題。首先從作業系統層面,檢視系統的 CPU、記憶體、I/O、網絡的使用率是否存在異常,再通過指令查找異常日志,最後通過分析日志,找到導緻瓶頸的原因;還可以從 Java 應用的 JVM 層面,檢視JVM 的垃圾回收頻率以及記憶體配置設定情況是否存在異常,分析日志,找到導緻瓶頸的原因。

如果系統和 JVM 層面都沒有出現異常情況,我們可以檢視應用服務業務層是否存在性能瓶頸,例如 Java 程式設計的問題、讀寫資料瓶頸等等。

分析查找問題是一個複雜而又細緻的過程,某個性能問題可能是一個原因導緻的,也可能是幾個原因共同導緻的結果。我們分析查找問題可以采用自下而上的方式,而我們解決系統性能問題,則可以采用自上而下的方式逐級優化。

3.1. 優化代碼

應用層的問題代碼往往會因為耗盡系統資源而暴露出來。例如,我們某段代碼導緻記憶體溢出,往往是将 JVM 中的記憶體用完了,這個時候系統的記憶體資源消耗耗殆盡了,同時也會引發 JVM 頻繁地發生垃圾回收,導緻 CPU 100% 以上居高不下,這個時候又消耗了系統的 CPU 資源。還有一些是非問題代碼導緻的性能問題,這種往往是比較難發現的,需要依靠我們的經驗來優化。例如,我們經常使用的 LinkedList 集合,如果使用 for 循環周遊該容器,将大大降低讀的效率,但這種效率的降低很難導緻系統性能參數異常。

這時有經驗的同學,就會改用 Iterator (疊代器)疊代循環該集合,這是因為 LinkedList 是連結清單實作的,如果使用 for 循環擷取元素,在每次循環擷取元素時,都會去周遊一次 List,這樣會降低讀的效率。

3.2.優化設計

面向對象有很多設計模式,可以幫助我們優化業務層以及中間件層的代碼設計。優化後,不僅可以精簡代碼,還能提高整體性能。例如,單例模式在頻繁調用建立對象的場景中,可以共享一個建立對象,這樣可以減少頻繁地建立和銷毀對象所帶來的性能消耗。

3.3.優化算法

好的算法可以幫助我們大大地提升系統性能。例如,在不同的場景中,使用合适的查找算法可以降低時間複雜度。

3.4.時間換空間

有時候系統對查詢時的速度并沒有很高的要求,反而對存儲空間要求苛刻,這個時候我們可以考慮用時間來換取空間。

3.5.空間換時間

這種方法是使用存儲空間來提升通路速度。現在很多系統都是使用的 MySQL 資料庫,較為常見的分表分庫是典型的使用空間換時間的案例。

3.6.參數調優

以上都是業務層代碼的優化,除此之外,JVM、Web 容器以及作業系統的優化也是非常關鍵的。

根據自己的業務場景,合理地設定 JVM 的記憶體空間以及垃圾回收算法可以提升系統性能。例如,如果我們業務中會建立大量的大對象,我們可以通過設定,将這些大對象直接放進老年代。這樣可以減少年輕代頻繁發生小的垃圾回收(Minor GC),減少 CPU 占用時間,提升系統性能。

Web 容器線程池的設定以及 Linux 作業系統的核心參數設定不合理也有可能導緻系統性能瓶頸,根據自己的業務場景優化這兩部分,可以提升系統性能。

3.7.兜底政策,確定系統穩定性

上邊講到的所有的性能調優政策,都是提高系統性能的手段,但在網際網路飛速發展的時代,産品的使用者量是瞬息萬變的,無論我們的系統優化得有多好,還是會存在承受極限,是以為了保證系統的穩定性,我們還需要采用一些兜底政策。

什麼是兜底政策?

第一,限流,對系統的入口設定最大通路限制。這裡可以參考性能測試中探底接口的 TPS 。同時采取熔斷措施,友好地傳回沒有成功的請求。

第二,實作智能化橫向擴容。智能化橫向擴容可以保證通路量超過某一個門檻值時,系統可以根據需求自動橫向新增服務。

第三,提前擴容。這種方法通常應用于高并發系統,例如,瞬時搶購業務系統。這是因為橫向擴容無法滿足大量發生在瞬間的請求,即使成功了,搶購也結束了。

目前很多公司使用 Docker 容器來部署應用服務。這是因為 Docker 容器是使用 Kubernetes 作為容器管理系統,而 Kubernetes 可以實作智能化橫向擴容和提前擴容 Docker 服務。

總結

Java性能調優實戰-如何制定性能調優政策?                                    如何制定性能調優政策?

繼續閱讀