当线上接口请求过慢如何排查?

线上接口过慢,排除网络的原因之外无非有以下三点:
1.内存使用过高,频繁gc导致cpu占满
2.内存使用不高,出现了类似死循环场景
3.死锁
一般在遇到问题的时候先使用top -c 命令查看cpu是否占满,然后再使用free -m查看内存使用率,初步判断是上面问题的哪一种,然后再针对这一种问题深入排查。下面来模拟一下以上几种情况:

内存使用过高导致CPU满载

案例代码

public class FullGc {
    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < 10000000; i++) {
            String str = "";
            for (int j = 0; j < 1000; j++) {
                str += UUID.randomUUID().toString();
            }
            list.add(str);
            System.out.println(str);
        }
    }

}

启动:java FullGc -Xms200m -Xmx200m

分析思路

  1. 查看负载高的cpu进程id: top -c
    在这里插入图片描述
    这时发现进程id为70719的cpu负载较高
  2. 查看该进程id的线程id: top -Hp 70719
    在这里插入图片描述
    这时发现线程id为70720的线程负载较高
  3. 将十进制的线程id转换为16进制小写的:printf "%x\n" 69476
    在这里插入图片描述
    发现16进制的线程id为11440
  4. 查看该线程的运行的情况:jstack 70719|grep 11440 -A60
    在这里插入图片描述
    发现是FullGc这个类的第14行有问题
  5. 通过jamp工具导出内存日志,分析堆的情况:jmap -dump:format=b,file=dump.dat 70719
    在这里插入图片描述
  6. 使用MAT工具分析堆的情况
    在这里插入图片描述
    发现了以上大量的字符串

出现了类似死循环导致cpu负载

案例代码

public class Cpu {
    public static void main(String[] args) {
        while (true) {
        }
    }
}

分析思路

基本上跟内存使用率过高的前几步差不多的,依然是以下几步:

  1. top命令查看当前CPU消耗过高的进程,得到进程id
  2. 根据进程id得到占比较高的线程id
  3. 将线程id转换为十六进制
  4. 根据进程编号用jstack命令查看线程id,可以得到线程的具体堆栈信息
    在这里插入图片描述
    从图中可以看出Cpu这个类的第三行有问题

死锁

案例代码

public class DeadLock {
    private static Object left = new Object();
    private static Object right = new Object();

    private static class Thread1 implements Runnable {
        @Override
        public void run() {
            synchronized (left) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
                synchronized (right) {
                }
            }
        }
    }

    private static class Thread2 implements Runnable {
        @Override
        public void run() {
            synchronized (right) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
                synchronized (left) {
                }
            }
        }
    }

    public static void main(String[] args) {
       new Thread(new Thread1()).start();
       new Thread(new Thread2()).start();
    }
}

分析思路

这个就简单了

  1. 先使用jps查看进程id,如图:
    在这里插入图片描述
  2. 找出死锁的线程:jstack [进程id]
    在这里插入图片描述
    jvm会自动搜索出死锁的堆栈信息
  • 13
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值