17 June 2020

CPU飙高

  • top查所有进程占用CPU的排序
  • top -Hp 进程号,找到进程下线程占用CPU的情况,找到占用CPU最高的线程编号
  • 执行print %x 线程号,转换成16进制,因为线程堆栈都是16进制数字
  • 执行jstack 进程号 grep 线程号,查看线程堆栈信息,找到具体代码
  • 线上除这种问题,应该没有这个时间去这么处理问题
    • 首先判断有没有计算密集型的这种任务
    • full gc导致cpu飙高(看堆情况,这个时候在jmap导出的话,有可能服务直接就死了,最好arthas)
      • 为什么会full gc呢,batch insert插入大量的数据,每个插入都对应大对象,同时因为大批量的数据插入导致慢sql的出现,数据库链接被占用的更多,批量新增大对象的队列都满了,数据也没有释放,开始full gc,消耗cpu资源,导致问题出现
      • 死循环(最好arthas)
  • 解决方案
    • 一般情况都不需要改回收机制,一般都是代码不规范的问题。考虑有没有大对象(大对象不止会OOM,也会cpu飙高,因为放不下这OOM,放的下full gc)
    • 监控慢sql,这种存储媒介的资源很少,很重要,只要被异常占用,大概率会出问题

Arthas

线上OOM

  • 简介:请求进来,创建对象,去内存里面申请空间,内存满了,触发full gc,gc之后内存依然爆满,OOM
  • 影响
    • 新请求不需要申请堆内存空间,正常用
    • 新请求需要申请堆内存空间,进程飙高,操作系统认为危险,杀进程,服务宕机
  • 解决
    • 已经OOM宕机了,直接看dump文件,用jvm那个自带的工具分析下对象找到gcRoot,之后找到线程栈,之后找到问题
    • 没有OOM宕机,如果执行jmap导出dump,会进行gc,会stop the world,很危险,所以最好用arthas

负载高,cpu低

  • cpu负载值 = running 状态 + interruptible 状态的进程个数之和 。也就是说,如果负载值超过cpu核数,那表示出现了以下两种情况:
    • 等待分配cpu资源的进程多了
    • 等待磁盘I/O完成的进程多了
  • 而导致等待磁盘I/O完成的进程过多的原因,又可能有如下几种情况
    • 磁盘读写请多,导致大量I/O等待:前面通过 iostat 查看没有发现。
    • MySQL存在没有索引的语句或存在死锁:服务器上个没有MySQL,而且通过前面查看,I/O请求量很少。
    • 外接硬盘故障,常见如挂载NFS,但是NFS server 故障:这个问题会导致,大量请求无法获取到资源,从而interruptible 状态进程增多,负载增大

频繁full gc

  • 首先看堆的变化情况,是否是缓慢增长还是一下子打满?
    • 缓慢增加,有可能是内存泄露
    • 一下子打满,应该是大对象进入,来源有可能是数据库,mq,内存主动产生
      • 此时已经无法去打印出堆内存的情况了,因为cpu已经被打满了,首先排查数据库的问题
      • 如果是数据库的话,查看是否有数据量过大的sql传输。


blog comments powered by Disqus