CPU飙高问题排查思路

目录

前言

CPU飙高原因

流量激增

程序代码

Full GC


前言

工作中时不时会被指派去排查线上问题,线上问题大致分成两种:

一种是业务bug相关的,这种实际上没啥好讲的,无非就是程序运行结果不符合业务,一般都是看下相关日志,获取相关入参,在本地复现bug后修复即可。

另一种则是排查程序是否能稳定运行,即在程序能完成预期的功能前提下,保证程序能够有较快的响应速度,不会出现明显的卡顿以及延迟。一般出现延迟或者卡顿的情况,服务器CPU使用率通常都会异常飙高。

所以问题也就转换成了排查CPU为何飙高,以及应该如何解决。

CPU飙高原因

CPU使用率突然飙高,可以尝试用以下的思路逐步排查

  1. 流量激增
  2. 程序代码存在问题
  3. 针对Java程序,频繁Full GC

流量激增

如果是在短时间内访问流量突然变多,系统的并发量变大,从而导致CPU突然飙高,这种情况导致CPU飙高其实是正常的,很多情况下并不需要去做调整。因为这并不是程序本身有问题,而是突发的流量一时间超过了系统设计的阈值。

针对这种场景,解决的思路一般都是开源节流,削峰填谷

开源:即加机器,水平扩展应用程序

节流:即对接口进行限流,保证并发不会超过设计的阈值,防止程序崩溃

削峰填谷使用消息队列作为一个缓冲层,将高峰期的请求先保存到消息队列中,然后由消费者按照自己的处理能力从队列中取出消息进行处理。

程序代码

如果是程序代码写的不好导致的CPU飙高,那么这个是必须要排查并且及时修复的。

代码中存在了死循环反复初始化单例对象一次性创建很多对象创建大对象等等耗时的操作,都会导致程序在运行时CPU飙高。

具体情况还需要具体分析,在线上环境中,一般服务都是部署在Linux上,可以通过 top + jstack 来帮助定位问题代码

使用 top 命令来查看CPU使用情况

top

找到CPU占用最高的Java进程ID后,使用 top -Hp 来查看对应 Java 进程的线程详情

-H:在进程信息中显示线程详细信息。

-p <进程ID>:仅显示指定进程ID的信息。

top -Hp 进程ID

 找到CPU占用最高的Java线程ID,将线程ID转换成16进制

printf '%x\n' 线程ID

 得到线程ID十六进制后,使用 jstack + grep 输出该线程的详细栈信息

grep -A <显示行数>:除了显示符合范本样式的那一列之外,并显示该行之后的内容。

jstack Java进程ID | grep -A 200 Java线程ID十六进制

 输出栈信息后,便可以分析是具体哪一行代码导致线程运行时间长了。

Full GC

针对 Java 程序,垃圾回收器频繁地进行Full GC,也会导致CPU飙升。

频繁 Full GC 的原因可能是:

应用程序存在内存泄漏,老年代有效空间变小,每次Full GC 后释放的空间也有限,所以频繁Full GC

方法运行中创建了很多大对象,新生代放不下,直接在老年代进行分配空间,导致老年代一下子就满了需要进行 Full GC,若是方法的并发量大,则 Full GC 会非常频繁。

在Linux服务器中,可以使用 jstate 来查看 Java 应用程序 GC 情况

jstat -gc Java进程ID

 可以使用 jmap 来导出堆栈信息

jmap dump:format=b,file=dump.hprof Java进程ID

 导出的hprof文件,可以使用JDK自带的JVM分析工具 jvisualvm 进行分析,排查是否发生内存泄漏,即查看堆中是否存在某些对象占用了特别大的空间。

  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值