POI导出数据至Excel,cpu飙升 cpu占用很高,原因排查

零 干货满满 

1测试环境开启GC日志

-Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC 

2 GC日志在线析平台 将gc日志导入,方便可视化查看Universal JVM GC analyzer - Java Garbage collection log analysis made easyhttps://gceasy.io/https://gceasy.io/

3 常用定位Cpu的linux命令((复制粘贴直接用)运气好的话,这几个命令执行完,就找到了代码中的问题)

# 高cpu
#linux命令1 所有进程的系统使用情况,确定是不是自己的应用cpu高
top
#2 找到自己的进程id
ps -ef|grep edp.DavinciServerApplication
#3 找到自己进程下的最占用cpu的线程
top -Hp 进程id
#4 将线程ID转为16进制,目的是为了在jstack生成的信息中进行查找
printf "%x\n" 线程ID
#5 打印进程信息,查看该线程的执行代码栈信息
 jstack 进程ID |grep 线程ID十六进制 -A 30

4arthas 使用解决问题。(上边linux命令不好解决,用这个,复制粘贴直接用)

# 1下载arthas,一共就148kb 很快
curl -O https://alibaba.github.io/arthas/arthas-boot.jar

# 2启动arthas,启动后找到自己的程序ID,输入ID,回车。
java -jar arthas-boot.jar

# 3查看信息命令
dashboard 

# 4 查看最占用cpu的三个线程的信息。
thread -n 3 

# 5 根据打印的代码信息,找到代码中写的不合适的地方,进行修改。

5 火焰图生成查看。(查看系统中哪些代码占用cpu)

#arthas中使用
profiler start

# 等待几十秒后执行
profiler stop 

生成html文件打开就好

一 背景说明

项目中用到了POI进行导出数据,当数据量比较大时,会出现CPU超过百分之百的问题,引发报警,因为是数据分析平台,报警非常随机,当同时下载的用户比较多时,且数据量很大时,就会引发报警。

二 排查流程

1 网上百度大部分说Cpu问题是频繁gc导致的,首先查看prometheus,只能发现Eden区是比较满的,gc也不是很频繁。于是又在测试环境,配置了项目启动的gc日志,启动脚本中增加以下参数:

-Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC 
if [[ $1 = "development" ]] || [[ $1 = "testing" ]]; then
  sleep 3s
  nohup $JAVA_HOME/java -Dlog4j2.formatMsgNoLookups=true -Dfile.encoding=UTF-8 -Dspring.profiles.active=$ENV -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8913 -cp $JAVA_HOME/lib/*:lib/* -Xmx28672m -Xms28672m -Xmn14336m -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M -Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC edp.DavinciServerApplication >$LOG_PATH 2>&1 &
else
  nohup $JAVA_HOME/java -Dlog4j2.formatMsgNoLookups=true -Dfile.encoding=UTF-8 -Dspring.profiles.active=$ENV -cp $JAVA_HOME/lib/*:lib/* -Xmx28672m -Xms28672m -Xmn14336m -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M edp.DavinciServerApplication >$LOG_PATH 2>&1 &
fi

于是在相应的路径下找到GC日志信息,将gc日志导入到分析可以看到也不频繁,而且没有full gc。所以可以排除是频繁gc导致的cpu过高的问题。Universal JVM GC analyzer - Java Garbage collection log analysis made easyFree online java GC log analyzer. Analyze JVM, Android garbage collection logs. Troubleshoot long GC pause, memory leak, OutOfMemoryError. Java GC tuning, memory settings tunning made easyhttps://gceasy.io/

 2 进行代码栈查看,寻找是否有高计算的代码,或者是频繁切换线程的代码。

首先用的是linux的命令进行操作

# 高cpu
#linux命令1 所有进程的系统使用情况,确定是不是自己的应用cpu高
top
#2 找到自己的进程id
ps -ef|grep edp.DavinciServerApplication
#3 找到自己进程下的最占用cpu的线程
top -Hp 进程id
#4 将线程ID转为16进制,目的是为了在jstack生成的信息中进行查找
printf "%x\n" 线程ID
#5 打印进程信息,查看该线程的执行代码栈信息
 jstack 进程ID |grep 线程ID十六进制 -A 30

但是我的情况比较特殊,我是一个下载线程池的多个线程下载生成excel,一个线程池的多个线程sheet生成,所以线程会有切换,不是一个线程持续cpu高的情况,等我将线程id转为16进制,再去jstack,查看的时候已经是waiting状态了。所以一直没有跟踪出问题代码所在。

然后查到arthas比较好用,所以下载尝试使用

# 1下载arthas,一共就148kb 很快
curl -O https://alibaba.github.io/arthas/arthas-boot.jar

# 2启动arthas,启动后找到自己的程序ID,输入ID,回车。
java -jar arthas-boot.jar

# 3查看信息命令
dashboard 

# 4 查看最占用cpu的三个线程的信息。
thread -n 3 

# 5 根据打印的代码信息,找到代码中写的不合适的地方,进行修改。

通过打印最占用cpu的三个线程的信息,发现代码中有个解析json的代码,在for循环中,由String解析为json比较占用cpu。

将该代码修改到for循环外边进行执行。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值