JVM 线上问题定位实战(CPU 飙升问题)

本文详细介绍了如何定位和解决JVM线上问题,特别是CPU占用过高和内存飙升的情况。通过模拟场景,展示了从问题描述、复现、定位到解决的全过程,涉及jstack、top等工具的使用,以及线程分析和内存泄漏排查。
摘要由CSDN通过智能技术生成

问题描述

很多时候我们的系统在使用过程中经常出现卡顿的情况,或者请求变慢(延迟高)等等情况,然后运维人员跑来给你说写的什么垃圾代码,CPU 飙升,经常 100%,内存飙升。

如果你不知道怎么定位问题,觉得自己代码也找不出什么问题,那就说重启试试咯!!!

当然了,这种处理方式可以解决,但并不能从根本上解决问题,试想一下如果对于高并发的系统,你重启项目肯定是不行的,所以我们要找到问题的源头,因为我们程序都是跑在 JVM 里面的,所以上面的 2 种情况很可能是我们的代码出现了问题,比如常见的死循环,递归等等,当然这种就是比较明显的错误。大多数情况下我们能察觉出来,而对于比较难以察觉的代码问题,则需要我们在 JVM 的层面去解决,也就是所谓的 JVM 调优 。

问题如下:

  1. 系统 CPU 经常 100%,如何调优?
  2. 系统内存飙升,如何定位问题?

当然,有人会说,加内存,加服务器等等,我们要理解调优的目的,其目的是为了利用现有的内存来获取 高吞吐量 或者 低延迟 ,说白了就是花更少的钱做更多的事。

场景模拟

之前在公司做过一个差旅系统(类似携程,但针对的是企业用户),大概意思是年终要 定时 统计年终的差旅费用,包括机票,酒店费用报销等等,把数据从 MySQL 中取出来计算汇总,如下:

大概步骤:

  1. 从数据库中批量读取用户信息;
  2. 利用线程池多线程执行任务计算。

代码如下:

/**
 * VM参数: -XX:+PrintGC -Xms200M -Xmx200M
 * GC调优---生产服务器推荐开启(默认是关闭的)
 * -XX:+HeapDumpOnOutOfMemoryError
 */
public class FullGCProblem {
    //线程池
    private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50, new ThreadPoolExecutor.DiscardOldestPolicy());
​
    public static void main(String[] args) throws Exception {
        //50个线程
        executor.setMaximumPoolSize(50);
        while (true) {
            calc();
            // 休眠 100ms 模拟计算耗时
            Thread.sleep(100);
        }
    }
​
    /**
     * 模拟多线程执行任务计算
     */
    private static void calc() {
        List<UserInfo> taskList = getAllCardInfo();
        taskList.forEach(userInfo -> {
            executor.scheduleWithFixedDelay(() -> {
                userInfo.other();
            }, 2, 3, TimeUnit.SECONDS);
        });
    }
​
    /**
     * 模拟从数据库读
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值