写点什么

线上程序 cpu 占用过高、程序死锁,该如何定位问题?

用户头像
码农架构
关注
发布于: 2021 年 06 月 17 日

假定你已经了解了运行时的数据区域和常用的垃圾回收算法,也了解了 Hotspot 支持的垃圾回收器

场景一:CPU 占用过高

cpu 占用过高要分情况讨论,是不是业务上在搞活动,突然有大批的流量进来,而且活动结束后 cpu 占用率就下降了,如果是这种情况其实可以不用太关心,因为请求越多,需要处理的线程数越多,这是正常的现象。话说回来,如果你的服务器配置本身就差,cpu 也只有一个核心,这种情况,稍微多一点流量就真的能够把你的 cpu 资源耗尽,这时应该考虑先把配置提升吧。


cpu 占用率长期过高,这种情况下可能是你的程序有那种循环次数超级多的代码,甚至是出现死循环了,或者死锁的情况。这个时候该怎么排查定位问题?


  • 用 top 命令查看 cpu 占用情况



这样就可以定位出 cpu 过高的进程。在 linux 下,top 命令获得的进程号和 jps 工具获得的 vmid 是相同的。



  • 用 top -Hp 命令查看线程的情况



可以看到是线程 id 为 23835 这个线程一直在占用 cpu

  • 把线程号转换为 16 进制



记下这个 16 进制的数字,下面我们要用

使用详情可参阅以前文章


我这里还是用前天的工具去查看检查下使用Arthas 的thread命令查看当前线程的堆栈情况



通过jstack工具

输出现在的线程栈,再通过 grep 命令结合上一步拿到的线程 16 进制的 id 定位到这个线程的运行情况,其中 jstack 后面的 23835 是第(1)步定位到的进程号,grep 后面的是(2)(3)步定位到的线程号。

从输出结果可以看到这个线程处于运行状态

案例代码



场景二:程序死锁

死锁并没有第一种场景那么明显,web 应用肯定是多线程的程序,它服务于多个请求,程序发生死锁后,死锁的线程处于等待状态(WAITING 或 TIMED_WAITING),等待状态的线程不占用 cpu,消耗的内存也很有限,而表现上可能是请求没法进行,最后超时了。在死锁情况不多的时候,这种情况不容易被发现。

  • 开启 Arthas 查看线程

  • 按照 CPU 使用率查看线程信息



  • 显示指定线程的运行堆



发现了一个死锁,原因也一目了然



案例代码



总结

以上两种严格地说还算不上 jvm 的调优,只是用了 jvm 工具把代码中存在的问题找了出来。我们进行 jvm 的主要目的是尽量减少停顿时间,提高系统的吞吐量。但是如果我们没有对系统进行分析就盲目去设置其中的参数,可能会得到更坏的结果,jvm 发展到今天,各种默认的参数可能是实验室的人经过多次的测试来做平衡的,适用大多数的应用场景。如果你认为你的 jvm 确实有调优的必要,也务必要取样分析,最后还得慢慢多次调节,才有可能得到更优的效果。

用户头像

码农架构

关注

公众号:码农架构 2018.03.22 加入

专注于系统架构、高可用、高性能、高并发类技术分享

评论

发布
暂无评论
线上程序cpu占用过高、程序死锁,该如何定位问题?