线上java JVM问题排查
作者:霞落滿天
第一部分? 是我以前公司的一則正式案例:
第二部分 是我另一個博客上寫的主要是最近發(fā)現(xiàn)大家問的比較多就寫了此文
?
第一部分 線上真實(shí)故障案例
?
下面是一個老系統(tǒng),代碼寫的有點(diǎn)問題導(dǎo)致出現(xiàn)這樣一個JVM占比過高的問題,正常情況下也就是CPU負(fù)載不高的時(shí)候21:00左右的,也有30萬,但是再多一點(diǎn)30幾萬就是閾值,就會出現(xiàn)堆積。
這個隊(duì)列一直是增長的快。
這個是zabbix的CPU監(jiān)控圖,可以看出某些時(shí)段CPU會有性能毛刺:
?
經(jīng)過跟同事一起討論發(fā)現(xiàn)是系統(tǒng)框架中 kafka producer 使用了線程池,但設(shè)置較小,而消息量比較大,導(dǎo)致消息堆積
?
我建議在項(xiàng)目中,將線程數(shù)量加大。
下面是分析過程:
1、??????????從dump文件來看kafka.producer.KafKaProducerImpl這個對象中的queue占用了大量內(nèi)存,這個類應(yīng)該fx-kafka中提供的功能,用來寫業(yè)務(wù)kafka的;
從圖來看,堆內(nèi)存已經(jīng)占用了1.4G,可能存在內(nèi)存泄露風(fēng)險(xiǎn)。
?
2、????????建議查看一下dump文件中的線程消耗CPU情況,
a、可能是有線程在不停的循環(huán)造成的CPU過高;
b、?gc線程不停回收造成?
?
線上問題當(dāng)時(shí)的CPU占用情況如圖所示:
?
下面是當(dāng)時(shí)java內(nèi)存dump
?
?
?
=========================
第二部分 JVM常見排障步驟
0.jps
這個輸出java進(jìn)程pid
#jps
?
查看java的線程
#top -Hp 25448
如圖25757這個線程比較耗時(shí),看看他在做什么
注意需要折算出線程pid的16進(jìn)制值,然后jstack。
可以打印更多信息
#jstack pid | grep -A 20 649d
參考:JVM調(diào)優(yōu)之jstack找出最耗cpu的線程并定位代碼
top+jstack分析cpu過高原因
?
1.jstack
#jstack -l pid > jstack.log
使用jstack命令輸出這一時(shí)刻的線程棧
jstack線程分析
jstack日志深入理解
?
2.jmap
#jmap -dump:format=b,file=heapDump 6900
#jmap -dump:live,format=b,file=dump.bin ?6900
-dump:[live,]format=b,file=<filename> 使用hprof二進(jìn)制形式,輸出jvm的heap內(nèi)容到文件=.?
live子選項(xiàng)是可選的,假如指定live選項(xiàng),那么只輸出活的對象到文件.?
Java命令學(xué)習(xí)系列(3):Jmap
jmap查看堆內(nèi)存大小
#jmap -heap ?pid
注意:jmap使用的時(shí)候jvm是處在停頓狀態(tài)的,只能在服務(wù)不可用的時(shí)候?yàn)榱私鉀Q問題來使用,否則會造成服務(wù)中斷。
使用jmap -histo[:live] pid查看堆內(nèi)存中的對象數(shù)目、大小統(tǒng)計(jì)直方圖,如果帶上live則只統(tǒng)計(jì)活對象,如下:
# jmap -histo:live pid | more
?
需要使用MAT工具分析jmap dump的內(nèi)存
使用jmap和MAT分析JVM堆內(nèi)存
?
3.jstat
jstat -gcutil pid
250毫秒一次采樣4次
可以看出:
堆內(nèi)存 = 年輕代 + 年老代 + 永久代
年輕代 = Eden區(qū) + 兩個Survivor區(qū)(From和To)
現(xiàn)在來解釋各列含義:
S0C、S1C、S0U、S1U:Survivor 0/1區(qū)容量(Capacity)和使用量(Used)
EC、EU:Eden區(qū)容量和使用量
OC、OU:年老代容量和使用量
PC、PU:永久代容量和使用量
YGC、YGT:年輕代GC次數(shù)和GC耗時(shí)
FGC、FGCT:Full GC次數(shù)和Full GC耗時(shí)
GCT:GC總耗時(shí)
E、hprof(Heap/CPU Profiling Tool)
4.gcore
#gdb -q --pid=1990
(gdb) generate-core-file
(gdb) detach
(gdb) quit
jmap -dump:format=b,file=heap.hprof /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java core.1990?
需要具體jdk對應(yīng)的bin/java
參考:
gcore 獲取程序core dump file 但程序不用退出,gdb 分析core
java程序性能分析之thread dump和heap dump
?
5.堆外內(nèi)存泄露分析
top出來java占用內(nèi)存極大而jmap出來的很小,說明有堆外內(nèi)存泄露。
參考Java堆外內(nèi)存泄露分析
?
綜合使用參考:?JVM性能調(diào)優(yōu)監(jiān)控工具jps、jstack、jmap、jhat、jstat、hprof使用詳解
JVM性能調(diào)優(yōu)監(jiān)控工具專題一:JVM自帶性能調(diào)優(yōu)工具(jps,jstack,jmap,jhat,jstat,hprof)
JVM性能調(diào)優(yōu)監(jiān)控工具專題二:VisualVM基本篇之監(jiān)控JVM內(nèi)存,CPU,線程
下面一些寫的好,如果覺得前面不夠盡興可以延申閱讀
如何使用MAT進(jìn)行內(nèi)存泄露分析
jvm系列六、windows用jdk自帶工具jps、jstack找出性能最差的代碼?【windows下的比較實(shí)用】
JVM 發(fā)生 OOM 的 8 種原因、及解決辦法
面試官問:平時(shí)碰到系統(tǒng)CPU飆高和頻繁GC,你會怎么排查【評判標(biāo)準(zhǔn)】
1.如果是Full GC次數(shù)過多,那么通過jstack得到的線程信息會是類似于VM Thread之類的線程;
2.而如果是代碼中有比較耗時(shí)的計(jì)算,那么我們得到的就是一個線程的具體堆棧信息。
3.如果說該接口中有某個位置是比較耗時(shí)的,由于我們的訪問的頻率非常高,那么大多數(shù)的線程最終都將阻塞于該阻塞點(diǎn),這樣通過多個線程具有相同的堆棧日志,我們基本上就可以定位到該接口中比較耗時(shí)的代碼的位置。
4.waiting on condition
如果該線程本身就應(yīng)該處于等待狀態(tài),比如用戶創(chuàng)建的線程池中處于空閑狀態(tài)的線程,那么這種線程的堆棧信息中是不會包含用戶自定義的類的。這些都可以排除掉,而剩下的線程基本上就可以確認(rèn)是我們要找的有問題的線程。通過其堆棧信息,我們就可以得出具體是在哪個位置的代碼導(dǎo)致該線程處于等待狀態(tài)了。
5.deadlock死鎖這種情況基本上很容易發(fā)現(xiàn)
=========================
JVM很多時(shí)間是因?yàn)橄到y(tǒng)架構(gòu)不合理導(dǎo)致的,比如過大的內(nèi)存,其實(shí)系統(tǒng)只要稍微調(diào)整下,完全可以提前避免。推薦看看我精心制作的課程《高性能微服務(wù)架構(gòu)設(shè)計(jì)模式》你會對系統(tǒng)架構(gòu)有很大的提高。
高性能微服務(wù)架構(gòu)設(shè)計(jì)模式
主講:霞落滿天
現(xiàn)在企業(yè)開發(fā)都是微服務(wù)架構(gòu),但是有很多問題,比如分布式定義,分布式的微服務(wù)怎么拆分,什么時(shí)候拆分,怎么做到高性能,針對這些問題我錄制了一期學(xué)習(xí)視頻。有任何學(xué)習(xí)問題可以給我留言
視頻地址有試聽:https://edu.csdn.net/course/detail/27256/
課程大綱
開篇 高性能系統(tǒng)架構(gòu)的分布式理論基礎(chǔ)
模型 可無限擴(kuò)展的AKF立方
問題 億級QPS的電商網(wǎng)站遇到的問題
模式 CQRS模式進(jìn)行架構(gòu)設(shè)計(jì)
模式 事件溯源模式進(jìn)行架構(gòu)設(shè)計(jì)
結(jié)尾 新問題
課程精彩圖片分享:
總結(jié)
以上是生活随笔為你收集整理的线上java JVM问题排查的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个qq社会网名男生
- 下一篇: Windows下安装Mongodb S