记一次cpu 100%问题排查

Posted by 行如风 Blog on August 9, 2020

背景

服务器用的Openresty,代码用Lua+Php编写

处理

登录到机器,发现nginx一个worker进程出现了cpu 100%的情况:

使用pstack 多次查看该worker进程,也都是同样结果。

看来是代码出现了热循环,接下来要做的就是定位到热循环 的地方。

该接口除了使用lua外,还有c的扩展。

所以想着使用采样工具并生成火焰图来定位问题。这里使用春哥提供的 openresty-systemtap-toolkit 工具进行采样。(话说安装systemtap的过程遇到了点小麻烦,主要问题是linux内核版本被公司编译时修改了。具体安装可参考build-systemtap

使用c级别采样工具:

1
./sample-bt -p 16985 -u -t 10 > c.bt

然后使用FlameGraph生成火焰图

1
2
stackcollapse-stap.pl c.bt > c.cbt
flamegraph.pl c.cbt > c.svg

最终火焰图为:

可以看出并非c扩展代码导致,还是lua代码的问题。继续lua级别采样:

1
./ngx-lua-bt --luajit20 -p 16985 > lua.bt

但是发现直接卡住,若干分钟后仍没有动静。

火焰图直观定位是没法用了,只能使用gdb来调试了。

这里仍然使用春哥提供的openresty-gdb-utils工具。

安装参见openresty-gdb-utils#installation

在/home/root/目录下建立.gdbinit,写入

1
2
3
4
5
6
7
8
9
10
directory /path/openresty-gdb-utils-master

py import sys
py sys.path.append("/path/openresty-gdb-utils-master")

source luajit20.gdb
source ngx-lua.gdb
source luajit21.py
source ngx-raw-req.py
set python print-stack full

接下来就可以愉快的使用gdb来定位问题了。

总结:

  • lua程序,大多数问题是lua代码导致的。
  • 基本上采样很难奏效,此时可直接使用gdb调试
  • 在可能存在性能瓶颈的地方,要做好压测。