[ABI 5.2] CPU占用率过高,如何排查问题

10608
3

木兮 数据达人Lv4

发表于2021-9-26 14:51

悬赏1

已解决

楼主

这里显示cpu占用率过高,如何排查问题所在?

最近看过此主题的会员

ligaopeng

董先生

ESENSOFT官方技术支持

缱绻

夏琪

hesj

果冻出场

最佳答案
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导出的线程堆栈中找它是哪个线程,在做什么。
3个回答

只看楼主

果冻出场 数据小白Lv1

发表于2021-9-26 15:08

只看该作者

取消 关注该作者的回复

沙发

这里显示的是服务器的CPU.您可以去检查一下服务器的情况

木兮 数据达人Lv4

发表于2021-9-26 15:11

只看该作者

取消 关注该作者的回复

板凳

果冻出场 发表于 2021-9-26 15:08
这里显示的是服务器的CPU.您可以去检查一下服务器的情况

我需要知道Bi 有什么进程,导致服务器占用率这么大,服务器只有bi程序,没有其他的

果冻出场 数据小白Lv1

发表于2021-9-26 14:51

只看该作者

取消 关注该作者的回复

地板

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导出的线程堆栈中找它是哪个线程,在做什么。

登录后可回答问题,请登录注册

快速回复 返回顶部 返回列表

小时

全天响应

分钟

快速处理问题

工程师强势助力

明星产品
解决方案
联系合作

400咨询:400-0011-866

技术支持QQ:400-0011-866(工作日9:00-18:00)

产品建议邮箱yixin@esensoft.com

关注我们

扫TA学习更多干货

一对一专家交流

版权所有© 2006-2024 北京亿信华辰软件有限责任公司 京ICP备07017321号 京公网安备11010802016281号