【性能调优-实例演示】CPU爆了怎么定位问题--》调试指令&性能分析工具

性能调优

定位生产性能问题

生产环境,CPU Memory 告警

  1. top:找出占CPU比较高的进程${pid}(内存增长,CPU居高不下)
  2. top -Hp ${pid}:显示所有线程的CPU占比,观察进程中的线程,找出哪个线程CPU和内存占比高
  3. jps ${pid}定位具体java进程
  4. jstack 定位线程状况,重点关注:WAITING BLOCKED。 jstack能检查到死锁的存在,并显示哪些线程发生了死锁;
    在这里插入图片描述

1、是否有死锁:
waiting on <0x0000000088ca3310> (a java.lang.Object)
假如有一个进程中100个线程,很多线程都在waiting on ,一定要找到是哪个线程持有这把锁
怎么找?搜索jstack dump的信息,找 ,看哪个线程持有这把锁RUNNABLE。
2、根据线程编号,用jstack查看线程的调用栈信息,对比看是哪个线程一直在占用CPU。

  1. 若是VM线程,那就是一直在FGC,若是频繁FGC,需要看是否正常回收(回收不掉?内存泄露)
  2. 若是业务线程,则查看业务代码问题
  1. jinfo ${pid} 查看线程信息
  2. jstat -gc 动态观察gc情况 / 阅读GC日志发现频繁GC / arthas观察 / jconsole/jvisualVM/ Jprofiler(最好用)

jstat -gc ${pid} 500 : 每个500个毫秒打印GC的情况.

  1. jmap - histo 4655 | head -20,jmap主要被用来分析堆内存的工具,查找有多少对象产生

若是压测环境,可以直接用图形界面工具来分析(MAT/jhat/jvisualvm/arthas);
若是生产环境,线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(电商不适合),则用cmdline arthas 或以下步骤:

  • 提前设置好启动参数 -XX:HeapDumpOnOutOfMemoryError 当OOM内存爆了,就生成堆存储文件
  • 做负载均衡,把某一台机摘除流量后,再分析(或把流量复制一份到备份机,然后对备份机进行分析)
  • 使用TCP copy命令把流量复制并同时打到生产环境和测试环境,在测试环境做性能分析和观察
  • 在压测环境分析
  • 堆存储文件分析工具:MAT/jhat/jvisualvm
  • https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html
    jhat -J-mx512M xxx.dump
    http://192.168.17.11:7000
    拉到最后:找到对应链接
    可以使用OQL查找特定问题对象
  1. jmap - histo 4655 | head -20,查找有多少对象产生

工具篇

分析HeapDump文件

jconsole远程连接
  1. 程序启动加入参数:

    java -Djava.rmi.server.hostname=192.168.17.11 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=11111 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false XXX
    
  2. 如果遭遇 Local host name unknown:XXX的错误,修改/etc/hosts文件,把XXX加入进去

    192.168.17.11 basic localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    
  3. 关闭linux防火墙(实战中应该打开对应端口)

    service iptables stop
    chkconfig iptables off #永久关闭
    
  4. windows上打开 jconsole远程连接 192.168.17.11:11111

jvisualvm远程连接

https://www.cnblogs.com/liugh/p/7620336.html (简单做法)

arthas在线排查工具
  • 为什么需要在线排查?
    在生产上我们经常会碰到一些不好排查的问题,例如线程安全问题,用最简单的threaddump或者heapdump不好查到问题原因。为了排查这些问题,有时我们会临时加一些日志,比如在一些关键的函数里打印出入参,然后重新打包发布,如果打了日志还是没找到问题,继续加日志,重新打包发布。对于上线流程复杂而且审核比较严的公司,从改代码到上线需要层层的流转,会大大影响问题排查的进度。
  • jvm观察jvm信息
  • thread定位线程问题
  • dashboard 观察系统情况
  • heapdump + jhat分析
  • jad反编译
    动态代理生成类的问题定位
    第三方的类(观察代码)
    版本问题(确定自己最新提交的版本是不是被使用)
  • redefine 热替换
    目前有些限制条件:只能改方法实现(方法已经运行完成),不能改方法名, 不能改属性
    m() -> mm()
  • sc - search class
  • watch - watch method
  • 没有包含的功能:jmap

常见问题常见的问题有:

CPU异常高,甚至到100%

https://www.cnblogs.com/python-django-spid/p/16480423.html
思路:top 、top -Hp 查看使用CPU高的进程

进程一般存在7种基础状态:D-不可中断睡眠、R-可执行、S-可中断睡眠、T-暂停态、t-跟踪态、X-死亡态、Z-僵尸态。
D、S:SLEEP态进程不会占用任何CPU资源。
T、t、Z:暂停态、僵尸态 进程会释放所有占用资源。

user(us),代表用户态CPU时间
nice(ni),代表低优先级用户态时间
system(sys),代表内核态CPU时间
idle(id),代表空闲时间,注意不包括等待IO时间
iowait(wa),表示等待IO的CPU时间
irq(hi),代表处理硬中断的CPU时间
softirq(si),代表处理软中断的CPU时间
steal(st),代表当系统运行在虚拟机的时候,被其他虚拟机占用的CPU时间
guest(guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间
guest_nice(gnice),代表以低优先级运行虚拟机的时间
在这里插入图片描述

IOwait过高
JVM进程Hang

https://mp.weixin.qq.com/s/7SHlfonUEW8oWx_IAjuYRw

OOM(内存溢出)
内存泄露
频繁GC

示例

分析过程:

  1. top 找出占CPU高的进程 -->15856

  2. top -Hp 找出进程占CPU高的线程

  3. jps 列出本地或者远程主机上的所有JVM进程。(jps -lm 显示主类的全限定包名或者jar包的全路径名)

  4. jstack 主要JVM进程的线程栈信息:jstack 15856–》查看到没有死锁 WAITING BLOCKED
    在尾部看到有VM GC线程

  5. jmap -heap 15856 分代查看对内存使用情况
    新生代使用的少,老年代使用90%!
    在这里插入图片描述

在这里插入图片描述
jmap -histo 15856,查看堆内存直方图
查看堆内存直方图
jmap -dump:live,format=b,file=helen.hprof 15856,将java heap信息dump成hprof格式的二进制文件,子选项live被指定的时候,仅仅那些存活的堆内存中对象才会被dump出来。被dump出来的文件可以通过__jhat__工具查看

  1. jhat helen.hprof
    执行命令,分析完后会启动7000端口
    在这里插入图片描述
    访问http://localhost:7000/
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. Java自带工具jvisualVM.exe,分析hprof文件
    在这里插入图片描述
package com.vip.fcs.gc;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 从数据库中读取信用数据,套用模型,并把结果进行记录和传输
 */

public class T15_FullGC_Problem01 {

    private static class CardInfo {
        BigDecimal price = new BigDecimal(0.0);
        String name = "张三";
        int age = 5;
        Date birthdate = new Date();

        public void m() {}
    }

    private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50,
            new ThreadPoolExecutor.DiscardOldestPolicy());

    public static void main(String[] args) throws Exception {
        executor.setMaximumPoolSize(50);

        for (;;){
            modelFit();
            Thread.sleep(100);
        }
    }

    private static void modelFit(){
        List<CardInfo> taskList = getAllCardInfo();
        taskList.forEach(info -> {
            // do something
            executor.scheduleWithFixedDelay(() -> {
                //do sth with info
                info.m();

            }, 2, 3, TimeUnit.SECONDS);
        });
    }

    private static List<CardInfo> getAllCardInfo(){
        List<CardInfo> taskList = new ArrayList<>();

        for (int i = 0; i < 100; i++) {
            CardInfo ci = new CardInfo();
            taskList.add(ci);
        }

        return taskList;
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值