问题描述

没有呼叫的状态,cpu一直没有降下来,如下图所示:
image.png
freeswitch当前没有任何呼叫在跑,如下:
image.png
所以现在的目标是查看freeswitch哪个线程消耗cpu较多,以及因为什么原因在消耗cpu。

定位步骤

容器内安装htop和gdb

  1. yum install htop gdb -y

容器外安装nsenter

nsenter用于宿主机中侵入到容器内进行调试,默认情况下都是安装的。
未安装的话,请自行baidu安装步骤。

注:如果容器使用—privileged=true参数启动,权限较高,可以跳过后面步骤,直接进入容器使用gdb attach调试即可。

查看容器pid

  1. docker inspect -f {{.State.Pid}} <容器名称>

比如,我们此处查到的容器pid:
[root@bs tmp]# docker inspect -f {{.State.Pid}} testagent
899

查看容器内线程pid

  1. # 查看freeswitch进程
  2. ps -ef|grep free
  3. # 列出所有freeswitch的线程
  4. htop -p 28

此处我们选择的线程id是235,因为它占的比例最高,如下:
image.png
htop默认是显示所有线程的信息。

使用gdb查看线程堆栈

  1. nsenter -t 899 -m -p gdb -p 235

其中,899是容器pid, 235是容器内线程pid
如下,进入gdb之后,使用如下的命令查看线程堆栈信息:

(gdb) info threads
Id Target Id Frame
1 process 235 “eventThread” 0x00007f1dbfb54eb3 in epoll_wait () from /usr/lib64/libc.so.6
(gdb) thread 1
[Switching to thread 1 (process 235)]
#0 0x00007f1dbfb54eb3 in epoll_wait () from /usr/lib64/libc.so.6
(gdb) bt
#0 0x00007f1dbfb54eb3 in epoll_wait () from /usr/lib64/libc.so.6
#1 0x00007f1d811d046b in epoll_dispatch () from /usr/lib64/libalibabacloud-idst-speech.so
#2 0x00007f1d811bfad5 in event_base_loop () from /usr/lib64/libalibabacloud-idst-speech.so
#3 0x00007f1d811bf46b in event_base_dispatch () from /usr/lib64/libalibabacloud-idst-speech.so
#4 0x00007f1d80fb8947 in AlibabaNls::WorkThread::loopEventCallback(void
) () from /usr/lib64/libalibabacloud-idst-speech.so
#5 0x00007f1dc0500ea5 in start_thread () from /usr/lib64/libpthread.so.0
#6 0x00007f1dbfb548dd in clone () from /usr/lib64/libc.so.6

因为gdb直接调试的线程,所以info threads只查出来一个结果。
进入线程后,再使用bt就能打印出所有的堆栈信息。

这里能看到,是因为freeswitch里面封装的阿里asr模块导致的cpu一直居高不下。
这个就能定位出一个大概的方向,便于后面进一步定位。

根据这篇文件epoll 性能分析(解决占用CPU 过高问题)的分析,因为异常的参数设置,直接导致一个核被完全用满。

参考链接
如何在docker中进行gdb调试
Docker中使用GDB调试
epoll 性能分析(解决占用CPU 过高问题)