前言

在生产环境中有时会遇见服务器CPU超高的问题,特别是重大版本发布后如果有内存泄露很容出现CPU超高,严重可能会达到100%。现在我们使用的服务器都是多核CPU,当出现CPU告警我们需要及时发现问题代码并处置,不然严重情况下会导致服务器宕机。

如何快速定位

1、找到最耗CPU进程

2、找到最耗CPU线程

3、找到线程堆栈信息

4、找到问题代码并处置

定位工具top

top [-] [d] [p] [q] [c] [C] [S] [n]

参数:

d:指定每两次屏幕信息刷新之间的时间间隔,当然用户可以使用s交互命令来改变之

p:通过指定监控进程ID来仅仅监控某个进程的状态

q:该选项将使top没有任何延ch迟的进行刷新。如果调用程序有超级用户权限,那么top将以尽可能高的优先级运行

S:指定累计模式

s:使top命令在安全模式中运行。这将去除交互命令所带来的潜在危险

i:使top不显示任何闲置或者僵死进程

c:显示整个命令行而不只是显示命令名

H:显示线程

本次定位我们需要用到:

c:显示整个命令行而不只是显示命令名

H:显示线程

小试牛刀

我们以测试环境为例,找出最耗CPU线程堆栈并定位代码

1、找到最耗CPU的进程

  • 执行top -c ,显示进程运行信息列表,c参数作用是显示整个命令行
  • 键入P (大写p),进程按照CPU使用率排序

图示:

linux cpu system很高 linux cpu高怎么办_运维

如上图,最耗CPU的进程PID为1,查看命令行可以看到是loanOrder服务。

2、找到最耗CPU的线程

  • top -Hp 1 显示一个进程的线程运行信息列表,参数H就是显示线程,参数p则是仅仅监控pid
  • 键入P (大写p),线程按照CPU使用率排序

图示:

linux cpu system很高 linux cpu高怎么办_运维_02

如上图,进程1内,最耗CPU的线程PID为750。

3、找到线程堆栈信息

3.1 将线程PID转化为16进制,需要使用命令 printf "%x\n" 线程PID

[root@devops-01 /]# printf "%x\n" 750

2ee

如上750的16进制2ee,之所以要转化为16进制,是因为堆栈里线程id是用16进制表示的。

3.2 根据查到进程下线程750过滤得到堆栈信息,此时需要使用命令

jstack 进程PID | grep '线程PID' -C5 --color

jstack 1 | grep '2ee' -C5 --color

图示:

linux cpu system很高 linux cpu高怎么办_运维_03

如上图,找到了耗CPU高的线程对应的线程名称“http-nio-7014-exec-9"”,以及看到了该线程正在执行代码的堆栈。

4、根据堆栈信息找到问题代码并合理处置

目前是在锁等待的状态。在实际的内存泄露场景中,一般此时就会展示发生内存泄露的代码。

总结:用命令找到影响CPU的堆栈代码是最方便的,当然也可以采用arthas诊断工具,只是需要安装工具包然后也是看控制台找到线程ID,然后根据线程堆栈定位代码。