Java线上应用故障排查技巧--高Cpu占用

造成Java应用CPU高的原因

  1. 本身业务代码造成的CPU高
    • 存在死循环
    • 存在死锁
    • ...
  2. 内存不足,引发频繁的Full GC
  3. jvm的Bug
  4. ...

排查步骤

Java线上应用故障排查技巧--高Cpu占用_第1张图片

  1. 定位问题线程

    方法一:

     1.top命令找出消耗CPU高的Java进程及其线程id:
     	开启线程显示模式(top -H,或是打开top后按H)
     	按CPU使用率排序(top缺省是按CPU使用降序,已经合要求;打开top后按P可以显式指定按CPU使用降序)
     2.记下Java进程id及其CPU高的线程id
     	查看消耗CPU高的线程栈:
     	用进程id作为参数,jstack出有问题的Java进程
     	手动转换线程id成十六进制(可以用printf %x 1234)
     	在jstack输出中查找十六进制的线程id(可以用vim的查找功能/0x1234,或是grep 0x1234 -A 20)
    

    方法二:

     https://alibaba.github.io/arthas/index.html
     利用Arthas Thread分析
     wget https://arthas.gitee.io/arthas-boot.jar #下载Arthas
     java -jar arthas-boot.jar #启动后选择要分析的程序
     thread -n 5 #显示CPU最高的前五个线程栈
    

    方法三:

     https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#-show-busy-java-threads
     利用show-busy-java-threads脚本分析:
     wget https://raw.githubusercontent.com/oldratlee/useful-scripts/master/show-busy-java-threads
     chmod 755 show-busy-java-threads #赋权
     ./show-busy-java-threads ## 从所有运行的Java进程中找出最消耗CPU的线程(缺省5个),打印出其线程栈
    

    CPU使用率的含义

     Arthas的官方解释:
    

    Java线上应用故障排查技巧--高Cpu占用_第2张图片

    辅助手段:

     1.看Full GC次数:
     - jstat -gc PID # FGC对应的的Full GC的次数
     - springbootadmin
     - Arthas jvm命令
    
  2. 定位问题内存

    • dump内存快照

      方法一:jmap -dump:format=b,file=文件名 [pid]

      方法二:springbootadmin直接下载

    • 分析内存快照

      利用MemoryAnalyzer进行分析 Java线上应用故障排查技巧--高Cpu占用_第3张图片

      官网:https://www.eclipse.org/mat/

      网友教程:https://www.cnblogs.com/trust-freedom/p/6744948.html#leak_suspects

    • 辅助手段

      jmap -histo PID |head -n10 Java线上应用故障排查技巧--高Cpu占用_第4张图片

  3. 结合业务和代码分析原因

  4. 制定解决方案

    • 经验
    • 搜索技巧
    • 请教

真实案例

  1. ydtw-service:CPU时不时飙到1000~2000m

    使用Arthas thread命令查看线程情况

    Java线上应用故障排查技巧--高Cpu占用_第5张图片

    多次出现,初步判断此处消耗CPU

    结合代码进行分析和业务场景

    Java线上应用故障排查技巧--高Cpu占用_第6张图片

    业务场景:解析微信的xml数据,频繁调用该方法

    xsteam官网

    Java线上应用故障排查技巧--高Cpu占用_第7张图片

    改造单例模式后

    Java线上应用故障排查技巧--高Cpu占用_第8张图片

    效果:CPU稳定在200-300M

  2. ytj-config-service 部分节点CPU一值100%

    top:

    Java线上应用故障排查技巧--高Cpu占用_第9张图片

    Arthas:

    Java线上应用故障排查技巧--高Cpu占用_第10张图片

    show-busy-java-threads 脚本:

    Java线上应用故障排查技巧--高Cpu占用_第11张图片

    jstack

    Java线上应用故障排查技巧--高Cpu占用_第12张图片

    C2 CompilerThread:JIT即时编译器

    将字节码编译为本地代码,但是会启用一些编译耗时较长的优化

    https://www.jianshu.com/p/fbced5b34eff

    怀疑:JDK的BUG

    措施:升级JDK(8u111->8u212-b04)

  3. ydtp-backend-service CPU高,业务不正常

    按照上述方法进行分析,发现几百次Full GC->内存问题->dump内存快照

    Java线上应用故障排查技巧--高Cpu占用_第13张图片

    分析该SQL作用->把不开闸消息转存到历史表且没有分页;原因:某一体机疯狂发送不开闸消息到平台,共10几万条,触发转存操作。

    解决方案:临时删除消息表该通道的数据;平台加防护机制+解决转存性能+排查为什么为疯狂发送数据(一体机)

  4. aomp-service-grey 早上6:00~8:00 CPU飙到 170%+

    aomp-service-grey没人访问->定时任务->AOMP大屏-车牌城市分布每日汇总

    Java线上应用故障排查技巧--高Cpu占用_第14张图片

    两分钟不到 FullGC次数暴涨几十次

    Java线上应用故障排查技巧--高Cpu占用_第15张图片

    前两个都是垃圾回收的线程->即频繁的FullGc造成的Cpu高->分析内存

     jmap -dump:format=b,file=aomp-grey.bin 8 #dump内存 2.1G
     tar -zcvf aomp-grey.tar.gz aomp-grey.bin #压缩 500M
    

    Java线上应用故障排查技巧--高Cpu占用_第16张图片

    Java线上应用故障排查技巧--高Cpu占用_第17张图片

    代码:

    Java线上应用故障排查技巧--高Cpu占用_第18张图片

    Mybatis的一级缓存

    • 即session缓存,作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空,默认开启。

    • 注意 集成spring(使用mybatis-spring)时:

      • 每次查询spring会重新创建SqlSession,所以一级缓存是不生效的。
      • 而当开启事务时,spring会使用同一个SqlSession做查询,所以这个情况下一级缓存是生效的

    Java线上应用故障排查技巧--高Cpu占用_第19张图片

    • 解决方案:循环查询方法不要包含在事务里

    • 延伸问题:

      //在同一事物 Long id = 100L; ClassA a = mybatisSessionCacheTestService.queryById(id); ClassA b = mybatisSessionCacheTestService.queryById(id); //assert mybatis cache is on Assert.assertTrue(a == b); a.setXX(xx);//b的XX也被改变了,因为他们就是同一个对象

转载于:https://my.oschina.net/u/1241604/blog/3096598

你可能感兴趣的:(Java线上应用故障排查技巧--高Cpu占用)