JVM 常用工具和優化
JDK 自帶的
jconsole
jvisualvm
三方的工具
arthas
調優關注點(記憶體、GC):
記憶體
- MAT
- XElephant
- 在線:perfma
GC
拿到GC日志,分析GC日志(吞吐量,停頓時間,垃圾回收次數;這三個是評判垃圾收集器好壞的標準)
- 本地:GCViewer
- 在線:gceasy.io
在什么情況下調優
體現系統性能的參考因素
首先我們需要知道系統當前的運行狀況,也就是系統的性能好壞,才能判斷是否需要調優,如果系統的回應時間很短,計算機的資源使用也很低,那我們做系統調優就完全是為了調優而調優,那么衡量系統性能的指標到底有哪些呢?
- 回應時間:回應時間是衡量系統性能的重要指標之一,回應時間越短,性能越好,一般一個介面的回應時間是在毫秒級,回應時間還包括資料庫回應時間、服務端回應時間、網路回應時間、客戶端回應時間,
- TPS:指系統介面的 TPS(每秒事務處理量),因為 TPS 體現了介面的性能,TPS 越大,性能越好,在系統中,吞吐量分為兩種:磁盤吞吐量和網路吞吐量,
- 計算機資源分配使用率:通常由 CPU 占用率、記憶體使用率、磁盤 I/O、網路 I/O 來表示資源使用率,這幾個引數好比一個木桶,如果其中任何一塊木板出現短板,任何一項分配不合理,對整個系統性能的影響都是毀滅性的,
JVM 調優都做些什么?
具體來說 JVM 調優需要包括兩方面:合理地設定 JVM 的記憶體空間和選擇合適的垃圾回收器,
- 記憶體空間的分配設定:JVM 記憶體分配不合理帶來的性能表現并不會像記憶體溢位問題這么突出,最直接的表現就是頻繁的 GC,這會導致背景關系切換等性能問題,從而降低系統的吞吐量、增加系統的回應時間,具體的實作包括調整堆記憶體空間減少 Full GC、調整年輕代減少 MinorGC、設定合理的 Eden 和 Survivor 區的比例,
- 選擇合適的垃圾回收器:垃圾回收主要是指堆和方法區的回收,堆中的回收主要是物件的回收,方法區的回收主要是廢棄常量和無用的類的回收,垃圾收集器的種類很多,不同的場景有不同的選擇,對于每次操作的回應時間要求比較高的,我們可以選擇回應速度較快的 GC回收器,比如 CMS 回收器和 G1 回收器;而對系統吞吐量有較高要求時,就可以選擇 Parallel Scavenge 回收器來提高系統的吞吐量,
是否需要 JVM 調優?
一般專案肯定是不需要進行 JVM 調優的,因為 JVM 本身就是為這種低延時、高并發、大吞吐的服務設計和優化的,我們很少需要去改變什么,所以,我們往往更偏重于應用服務本身的調優,
在一些應用中,比如大資料計算引擎,是一種非常極端的 JVM 應用,對延時的要求并不高,但對吞吐量要求很高,會有大量的短生命周期物件產生,同時也有大量的物件生存時間非常久,我們就需要對特定的一些 JVM 引數進行修改,
再比如生產環境中出現記憶體溢位,我們需要判斷是由于大峰值下沒有限流,瞬間創建大量物件而導致的記憶體溢位,還是是由于記憶體泄漏而導致的記憶體溢位,對于記憶體泄漏導致的,這種問題就是程式的 Bug,我們需要及時找到問題代碼進行修改,而不是調整 JVM,
JVM 在很大程度上減輕了 Java 開發人員投入到物件生命周期管理的精力,在使用物件的時候,JVM 會自動分配記憶體給物件,在不使用的時候,垃圾回收器會自動回收物件,釋放占用的記憶體,所以一般情況下我們是不需要調優的,當然事無絕對,某些特殊場景就需要我們進行引數調整,但調整的前提一定是你對 JVM 的運行原理非常熟悉才行,
JVM錯誤排查與解決案例
JVM性能優化到底從發現到解決的歷程:發現問題-排查問題-解決問題
案列一:
發現問題:JVM日志 gc.log 檔案,通過JVM工具(比如:gceasy)查看并發現問題;比如GC的次數過多;可以通過工具查看到GC次數【新生代和老年代分別的GC次數】,GC頻繁:如何判斷GC頻繁呢?有個參照【比如服務剛上線GC5次,運行一段時間后10次,在之后30次,在之后50次,依次類推】
排查問題:列印出JVM GC日志,查看minorGC(新生代GC)或者majorGC(老年代GC)
解決問題:適當增加堆記憶體空間,或者選擇合適的垃圾收集器
案例二:
發現問題:OOM
排查問題:在JVM引數中配置,如果發生了OOM錯誤時自動dump下相關的.hprof檔案,對該檔案通過工具(比如MAT或者在線的perfma)進行分析;分析之后當找到占用記憶體比較大的物件對應的執行緒的業務代碼(可能是程式死回圈,或者后端程式并發量比較大)
解決問題:如果是并發量比較大,就減少對后端程式的訪問;通過Nginx增加機器,負載均衡,權重比例
案例三
發現問題:CPU負載過高
排查問題:命令:top jps jinfo jstat jmap 等這些命令靈活配合使用查看;可能是服務程式處理壓力過大
解決問題:具體看情況而論,可以集群部署、或者通過中間件(MQ、Kafka等)實作異步請求
案例四
發現問題:死鎖
排查問題:可以通過 jstack 命令去查看相關執行緒鎖的資訊
解決問題:找到對應的業務代碼,進行修改;或者使用zk、redis實作分布式鎖
案例五
發現問題:執行緒池不夠用了
排查問題:通過JDK的工具 jconcole jvisualvm 查看哪些執行緒得不到釋放的
解決問題:適當的對后端代碼優化,及時釋放資源、合理的設定執行緒池中的引數(大小)
趙小胖個人博客
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/187932.html
標籤:Java
上一篇:搭建Java環境
