-
-
木兮 数据达人Lv4
发表于2021-9-26 14:51
悬赏1
已解决

这里显示cpu占用率过高,如何排查问题所在?
使用jstack在压测经典慢场景下一定时间内连续导出多个java线程堆栈(3到5个),分析这几个线程堆栈,找到耗时所在jvm在较多频繁做什么操作。停留CPU消耗较多的地方通常就是耗时所在(结合linux的top命令更准确)。
使用如下命令找到服务器上所有的java进程(windows,如果是linux服务器,前面要带路径,当前文件夹是jdk的bin文件夹时用./jps):
jps
或使用(linux上)
ps -ef | grep java
使用如下命令输出java进程内的java线程执行信息(windows,如果是linux服务器,前面要带路径,当前文件夹是jdk的bin文件夹时用./jstack ...):
jstack -l <线程id> > jstack20201010.log
关于线程堆栈结果分析:
搜 com.esen
(1)可能停留在有锁的地方,查看 BLOCK 状态的地方,看能否优化锁粒度,减轻锁。
(2)通常,会停留在获取表结构(DbMetaDataCacheImpl#getTableMetaData)、等待数据库服务器返回查询结果(网络通讯)、有锁、网络IO通讯的地方。
(3)如果停留在RUNNABLE状态线程较多,要考虑是否该处代码不够优化,导致执行次数过多,尝试减少循环执行次数。
提供连续生成一个java进程的多个日志脚本,仅供参考(不用这个脚本,自己手工按上述方法生成也行,只需要多次执行jstack,且每次执行jstack时指定一个不同的文件名即可):
windows服务器:viewjlog61.batx.txt
对java进程12345 每隔5秒生成一个线程堆栈,共生成3个,并用gvim一起打开这批生成的文件
viewjlog61.bat 12345 5 3
.bat文件内容如下(仅供参考):
@Echo off
set INTERVAL_TIMEINSEC=%2
set LOGNUM=%3
set JAVA_THREAD_ID=%1
for /L %%i in (1, 1, %LOGNUM%) do (
"c:\program files\Java\jdk1.8.0_121\bin\jstack" -l %JAVA_THREAD_ID% > %temp%/jstackintv%JAVA_THREAD_ID%_%INTERVAL_TIMEINSEC%_%LOGNUM%_%%i.log
timeout /t %INTERVAL_TIMEINSEC% /nobreak
)
gvim %temp%/jstackintv%JAVA_THREAD_ID%_%INTERVAL_TIMEINSEC%_%LOGNUM%_*.log
注:
(1)其中JDK安装目录需要按实际需要修改,注意32位和64位JDK之分,需要用JDK,仅JRE还不够,
(2)生成到WINDOWS操作系统临时目录下,按WIN+R,或WIN+E,在地址栏中输入%temp%即可打开,然后找到以jstackintv和该java进程开头的日志文件,即可打开查看生成好的日志进行分析。
(3)打开日志的工具可选换成服务器本地已有的ultraedit/vscode/write/notepad等,也可直接克隆这些文件出来,发到开发机器上进行分析。
linux服务器:viewjlog61.shx.txt
对java进程12345 每隔5秒生成一个线程堆栈,共生成3个,放到/tmp/目录下,并用vi一起打开这批生成的线程日志文件
./viewjlog61 12345 5 3
.sh文件内容如下(仅供参考)
INTERVAL_TIMEINSEC=$2
LOGNUM=$3
JAVA_THREAD_ID=$1
echo "JAVA_HOME

for((i=1;$i<5;i++))
do
echo "i

$JAVA_HOME/bin/jstack -l $JAVA_THREAD_ID > /tmp/jstackintv${JAVA_THREAD_ID}_${INTERVAL_TIMEINSEC}_${LOGNUM}_$i.log
sleep $INTERVAL_TIMEINSEC
done
vi /tmp/jstackintv${JAVA_THREAD_ID}*.log
注意:通常4和5一起结合起来分析,才是利器。
5.占用资源分析
结合linux上的top/top -Hp等命令找到消耗CPU多的java进程、java线程,结合上面4的线程分析,通常能很快定位到持续慢的时候中间件CPU在做什么。
定位Linux上占用高的Java线程id
定位linux服务器上消耗CPU多的进程:
top
定位linux服务器上消耗CPU多的线程:
top -Hp <java进程id>
找到占用CPU时间最高的几个java线程的id,用工具将整数id转换成十六进制(windows:calc命令或计算器,linux用printf %x 12345),将得到的结果数值串,到第4节部分生成的jstack线程堆栈日志文件中搜索,找到占用高的线程在做什么。
定位Windows上占用高的Java线程id
可使用 微软官方提供的 Process Explorer 工具 。根据jps找到java进程后,右键在树形上相应节点项,查看属性-》Threads,按CPU占用倒序排序,找到前几个占用相对较高的线程,默认是十进制的,使用Windows上计算器(程序员)转成十六进制,到jstack导出的线程堆栈中找它是哪个线程,在做什么。
3个回答
4.java线程分析
使用jstack在压测经典慢场景下一定时间内连续导出多个java线程堆栈(3到5个),分析这几个线程堆栈,找到耗时所在jvm在较多频繁做什么操作。停留CPU消耗较多的地方通常就是耗时所在(结合linux的top命令更准确)。
使用如下命令找到服务器上所有的java进程(windows,如果是linux服务器,前面要带路径,当前文件夹是jdk的bin文件夹时用./jps):
jps
或使用(linux上)
ps -ef | grep java
使用如下命令输出java进程内的java线程执行信息(windows,如果是linux服务器,前面要带路径,当前文件夹是jdk的bin文件夹时用./jstack ...):
jstack -l <线程id> > jstack20201010.log
关于线程堆栈结果分析:
搜 com.esen
(1)可能停留在有锁的地方,查看 BLOCK 状态的地方,看能否优化锁粒度,减轻锁。
(2)通常,会停留在获取表结构(DbMetaDataCacheImpl#getTableMetaData)、等待数据库服务器返回查询结果(网络通讯)、有锁、网络IO通讯的地方。
(3)如果停留在RUNNABLE状态线程较多,要考虑是否该处代码不够优化,导致执行次数过多,尝试减少循环执行次数。
提供连续生成一个java进程的多个日志脚本,仅供参考(不用这个脚本,自己手工按上述方法生成也行,只需要多次执行jstack,且每次执行jstack时指定一个不同的文件名即可):
windows服务器:viewjlog61.batx.txt
对java进程12345 每隔5秒生成一个线程堆栈,共生成3个,并用gvim一起打开这批生成的文件
viewjlog61.bat 12345 5 3
.bat文件内容如下(仅供参考):
@Echo off
set INTERVAL_TIMEINSEC=%2
set LOGNUM=%3
set JAVA_THREAD_ID=%1
for /L %%i in (1, 1, %LOGNUM%) do (
"c:\program files\Java\jdk1.8.0_121\bin\jstack" -l %JAVA_THREAD_ID% > %temp%/jstackintv%JAVA_THREAD_ID%_%INTERVAL_TIMEINSEC%_%LOGNUM%_%%i.log
timeout /t %INTERVAL_TIMEINSEC% /nobreak
)
gvim %temp%/jstackintv%JAVA_THREAD_ID%_%INTERVAL_TIMEINSEC%_%LOGNUM%_*.log
注:
(1)其中JDK安装目录需要按实际需要修改,注意32位和64位JDK之分,需要用JDK,仅JRE还不够,
(2)生成到WINDOWS操作系统临时目录下,按WIN+R,或WIN+E,在地址栏中输入%temp%即可打开,然后找到以jstackintv和该java进程开头的日志文件,即可打开查看生成好的日志进行分析。
(3)打开日志的工具可选换成服务器本地已有的ultraedit/vscode/write/notepad等,也可直接克隆这些文件出来,发到开发机器上进行分析。
linux服务器:viewjlog61.shx.txt
对java进程12345 每隔5秒生成一个线程堆栈,共生成3个,放到/tmp/目录下,并用vi一起打开这批生成的线程日志文件
./viewjlog61 12345 5 3
.sh文件内容如下(仅供参考)
INTERVAL_TIMEINSEC=$2
LOGNUM=$3
JAVA_THREAD_ID=$1
echo "JAVA_HOMEJAVA_HOME"
for((i=1;$i<5;i++))
do
echo "ii"
$JAVA_HOME/bin/jstack -l $JAVA_THREAD_ID > /tmp/jstackintv${JAVA_THREAD_ID}_${INTERVAL_TIMEINSEC}_${LOGNUM}_$i.log
sleep $INTERVAL_TIMEINSEC
done
vi /tmp/jstackintv${JAVA_THREAD_ID}*.log
注意:通常4和5一起结合起来分析,才是利器。
5.占用资源分析
结合linux上的top/top -Hp等命令找到消耗CPU多的java进程、java线程,结合上面4的线程分析,通常能很快定位到持续慢的时候中间件CPU在做什么。
定位Linux上占用高的Java线程id
定位linux服务器上消耗CPU多的进程:
top
定位linux服务器上消耗CPU多的线程:
top -Hp <java进程id>
找到占用CPU时间最高的几个java线程的id,用工具将整数id转换成十六进制(windows:calc命令或计算器,linux用printf %x 12345),将得到的结果数值串,到第4节部分生成的jstack线程堆栈日志文件中搜索,找到占用高的线程在做什么。
定位Windows上占用高的Java线程id
可使用 微软官方提供的 Process Explorer 工具 。根据jps找到java进程后,右键在树形上相应节点项,查看属性-》Threads,按CPU占用倒序排序,找到前几个占用相对较高的线程,默认是十进制的,使用Windows上计算器(程序员)转成十六进制,到jstack导出的线程堆栈中找它是哪个线程,在做什么。