早上遭遇一起"线上 Java Web 占用 100%CPU"的紧急事件, 将排查处理过程记录如下。
- 仅有的三台机器同时报警, 初步估计是个普遍性问题. 迅速重启其中两台应用, 并负责提供服务. 第三台机器用于保留现场, 进行后续排查.
- 登上机器, 执行下列操作, 确定出现问题的线程栈.
* 确定Java进程号 <pid>
ps -ef | grep <app> | grep -v grep
* 确定耗费CPU资源的线程 <pid_sub>
ps -Lfp <pid>
ps -mp <pid> -o THREAD, tid, time
top -Hp <pid>
* 将线程号转变为十六进制(因为jstack中以十六进制确定线程ID)
printf "%x\n" <pid_sub>
--- 例如输出 54ee
* 在Java进程的jstack信息中确定 0x54ee 的位置
jstack <pid> | grep 54ee
--- 例如输出 "http-bio-7001-exec-4" #59 daemon prio=5 os_prio=0 tid=0x00002aaac2e5c000 nid=0x966 runnable [0x000000004434e000]...
--- 下面就是具体线程栈信息
- 通过问题线程栈确定业务逻辑位置, 最终定位到函数级别, 由此确定问题: 在一个特殊SQL文本的解析中, 存在indexOf返回-1, 并导致死循环的代码段, 细节不表.
- 教训: 代码测试一定要完善, 覆盖所有边界情况.