专栏首页北京马哥教育线上应用故障排查之一:高CPU占用

线上应用故障排查之一:高CPU占用

线上应用故障排查之一:高CPU占用

一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环。

以我们最近出现的一个实际故障为例,介绍怎么定位和解决这类问题。

根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障。

通过ps aux | grep PID命令,可以进一步确定是tomcat进程出现了问题。但是,怎么定位到具体线程或者代码呢?

首先显示线程列表:

ps -mp pid -o THREAD,tid,time

找到了耗时最高的线程28802,占用CPU时间快两个小时了!

其次将需要的线程ID转换为16进制格式:

printf "%x\n" tid

最后打印线程的堆栈信息:

jstack pid |grep tid -A 30

找到出现问题的代码了!

现在来分析下具体的代码:ShortSocketIO.readBytes(ShortSocketIO.java:106)

ShortSocketIO是应用封装的一个用短连接Socket通信的工具类。readBytes函数的代码如下:

?

public byte[] readBytes(int length) throws IOException {
    if ((this.socket == null) || (!this.socket.isConnected
())) {
        throw new IOException("++++ attempting to read from 
closed socket");
    }
    byte[] result = null;
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    if (this.recIndex >= length) {
           bos.write(this.recBuf, 0, length);
           byte[] newBuf = new byte[this.recBufSize];
           if (this.recIndex > length) {
               System.arraycopy(this.recBuf, length, newBuf, 0, 
this.recIndex - length);
           }
           this.recBuf = newBuf;
           this.recIndex -= length;
    } else {
           int totalread = length;
           if (this.recIndex > 0) {
                totalread -= this.recIndex;
                bos.write(this.recBuf, 0, this.recIndex);
                this.recBuf = new byte[this.recBufSize];
                this.recIndex = 0;
    }
    int readCount = 0;
    while (totalread > 0) { 
         if ((readCount = this.in.read(this.recBuf)) > 0) { 
                if (totalread > readCount) {
                      bos.write(this.recBuf, 0, readCount);
                      this.recBuf = new byte[this.recBufSize];
                      this.recIndex = 0;
               } else {
                     bos.write(this.recBuf, 0, totalread);
                     byte[] newBuf = new byte[this.recBufSize];
                     System.arraycopy(this.recBuf, totalread, 
newBuf, 0, readCount - totalread);
                     this.recBuf = newBuf;
                     this.recIndex = (readCount - totalread);
             }
             totalread -= readCount;
        }
   }
}

问题就出在标红的代码部分。如果this.in.read()返回的数据小于等于0时,循环就一直进行下去了。而这种情况在网络拥塞的时候是可能发生的。

至于具体怎么修改就看业务逻辑应该怎么对待这种特殊情况了。

最后,总结下排查CPU故障的方法和技巧有哪些:

1、top命令:Linux命令。可以查看实时的CPU使用情况。也可以查看最近一段时间的CPU使用情况。

2、PS命令:Linux命令。强大的进程状态监控命令。可以查看进程以及进程中线程的当前CPU使用情况。属于当前状态的采样数据。

3、jstack:Java提供的命令。可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。

4、pstack:Linux命令。可以查看某个进程的当前线程栈运行情况。

本文分享自微信公众号 - 马哥Linux运维(magedu-Linux)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2014-09-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何快速截取某段时间内的日志

    在排除故障时,需要分析发生故障的原因,避免再次出现同样的问题,需要对日志进行分析,截取故障前后时间段的日志。通常用正则表达式来获取某段时间的内的日志,比较繁琐。...

    小小科
  • sar 找出系统瓶颈的利器

    12. sar 找出系统瓶颈的利器 sar是System Activity Reporter(系统活动情况报告)的缩写。sar工具将对系统当前的状态进行取样,然...

    小小科
  • 看你用错了没!Linux必知必会之内存使用统计命令free

    本文由马哥教育面授班25期学员推荐,转载自互联网,作者为Alli,内容略经小编改编和加工,观点跟作者无关,最后感谢作者的辛苦贡献与付出。 本文详细介绍了Linu...

    小小科
  • RocketMQ 同步复制 SLAVE_NOT_AVAILABLE 异常源码分析

    最近在 RocketMQ 钉钉官方群中看到有人反馈说 broker 主从部署,在发布消息的时候会报 SLAVE_NOT_AVAILABLE 异常,报这个异常的前...

    张乘辉
  • 实现一个同步的RenderApplication

    逍遥剑客
  • vue 中使用threejs

    tianyawhl
  • 浅谈window桌面GUI技术及图像渲染性能测试实践

    从Windows Vista之后,desktop composition的部分就由Desktop Window Manager完成了(当然是启用Aero的情况下...

    高楼Zee
  • MATLAB调用pygame实现强化学习环境

    前面我们已经能够通过MATLAB调用Python操作键鼠,也在MATLAB环境中建立简单的环境来训练强化学习模型,比如matlab倒立摆环境建模,现在我们需要稍...

    万木逢春
  • Flutter开发:TextField常用属性的使用

    在flutter开发过程中,掌握常用组件的使用是必备技能,flutter常用的组件和App开发时候常用的控件基本一模一样,只是使用的方式不一样罢了。

    三掌柜
  • TRTC学习之旅(三)-- 使用vue+ts集成互动直播

    上次我们已经用vue+ts实现了多人会议室的搭建,这次我们继续在上次项目的基础上,实现互动直播功能。

    黑眼圈云豆

扫码关注云+社区

领取腾讯云代金券