MYSQL排查问题


场景

对于互联网公司,线上CPU飙升的问题很常见(例如某个活动开始,流量突然飙升时)。

线上系统突然运行缓慢,CPU飙升,甚至到100%,以及Full GC次数过多,接着就是各种报警:例如接口超时报警等。此时急需快速线上排查问题。

问题排查

不管什么问题,既然是CPU飙升,肯定是查一下耗CPU的线程,然后看看GC。

核心步骤

  1. 执行top命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。

  2. 执行top -Hp 进程号命令:查看java进程下的所有线程占CPU的情况。

  3. 执行printf "%x\n 10命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf “%x\n 10-》打印:a,那么在jstack中线程号就是0xa.

  4. 执行 jstack 进程号 | grep 线程ID 查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了

  5. 执行jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计),查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用jmap -heap 进程ID查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。

  6. 执行jmap -dump:format=b,file=filename 进程ID,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多。

案例: 1.通过top找出cpu高的PID

可以通过ps aux grep PID更详细看到这个进程是什么项目

2.top -H -pPID 找到CPU占用率比较高的线程tid 如:top -H -p21264

3.其次将需要的线程ID转换为16进制格式 printf “%x\n” tid 如 printf “%x\n” 21276 的十六进制是531c

4.通过jstack查看这个线程正在执行的东西 jstack pid |grep tid -A 50 如:jstack 21264 | grep 531c -A 50

原因分析

  1. 内存消耗过大,导致FULL GC次数过多

    执行步骤1-5: - 多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》步骤2 - 通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。–》步骤5

  2. 代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢 执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。

  3. 由于锁使用不当,导致死锁。 执行步骤1-4:如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。

  4. 随机出现大量线程访问接口缓慢 代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。

  5. 某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现; 执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • 2379. Minimum Recolors to Get K Consecutive Black Blocks
  • 2471. Minimum Number of Operations to Sort a Binary Tree by Level
  • 1387. Sort Integers by The Power Value
  • 2090. K Radius Subarray Averages
  • 2545. Sort the Students by Their Kth Score