记一次定位线上故障。线程维度

定位线上故障。线程维度

  1. top

  2. 按1,查看CPU利用率。按P(大写)按CPU占用率排序

    • us:用户空间占用CPU百分比
    • sy:内核空间占用CPU百分比
    • ni:用户进程空间内改变过优先级的进程占用CPU百分比
    • id:空闲CPU百分比
    • wa:等待输入输出的CPU时间百分比
  3. 按H(大写),查看线程性能信息,默认按照CPU占用排序。可能会出现三种情况:

    1. 第一种情况,某个线程一直CPU利用率100%,则说明是这个线程有可能有死循环,那么请记住这个PID。

    2. 第二种情况,某个线程一直在TOP十的位置,这说明这个线程可能有性能问题。

    3. 第三种情况,CPU利用率TOP几的线程在不停变化,说明并不是由某一个线程导致CPU偏高。

  4. 如果是第一种情况,也有可能是GC造成,我们可以用jstat命令看下GC情况,看看是不是因为持久代或年老代满了,产生Full GC,导致CPU利用率持续飙高,命令如下。

    Jstat -gcutil pid 间隔时间  打印次数
    

    确定是gc频繁的话,可以进一步确认一下,是哪部分代码执行的时候造成了cpu飙高,用jstack命令把线程的堆栈信息打印出来:

    jstack pid > t-pid.dump 
    

    dump出来的文件里面是线程对应的堆栈信息,线程id也就是nid是十六进制的,而我们用top命令看到的线程id是十进制的,所以我们要转换我们看到的线程id从十进制到十六进制:

    printf "%x\n" pid
    

    然后我们可以看到线程当前执行到哪段代码了,判断一下是不是这段代码导致的cpu飙高。不是的话就可以找其他原因了。

线程数过多导致线程切换频繁,加大CPU开销,问题定位

  1. 查看当前机器建立的TCP连接数

    netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n
    
  2. 使用jstack dump看看这些线程都在做什么

    jstack pid > /home/t_pid.dump
    
  3. 统计下所有的线程分别处于什么状态。发现大量线程处于waiting(on object monitor)状态

    grep java.lang.Thread.State t_pid.dump | awk '{print $2$3$4$5}' | sort | uniq -c
    
  4. 查看处于waiting(on object monitor)的线程信息。观察哪个程序的waiting状态比较多。

    grep -A 5 'WAITING' t_pid.dump
    
  5. 找到程序的配置信息,减少核心线程数的最大值(ps:线程不是越多越好,需要结合CPU多少、处理速度、业务计算多少来确定)

    <修改中间件或者程序配置>

  6. 重启程序,重新dump线程信息,再次进行统计,分析是否解决问题。

    重复1-4

涉及到的其他命令

  • 查看CPU信息

    cat /proc/cpuinfo
    
  • 查看内存信息

    cat /proc/meminfo
    
  • 查看Java线程数

    ps -eLf | grep java -c
    
  • 查看linux系统里打开文件描述符的最大值

    ulimit -u
    
  • 找到日志里TOP10的异常

    grep ‘Exception’ /home/admin/logs/XX.log |awk -F':|,' ‘{print $2}’|sort |uniq -c |sort -nr|head -10
    

    找到之后可以再用-A 2 -B 2,看定位出日志的前面2行和后面两行。

posted @ 2020-10-16 15:19  StivenYang  阅读(107)  评论(0编辑  收藏  举报