参考 >
- 确定进程信息
- 判断该进程是否在Docker容器中。使用
cat /proc/<pid>/cgroup
查看打印内容是否包含:/docker/
。原理是Docker使用了Linux cgroups - 使用
pstree -s <pid>
查看打印的进程树是否包含docker-containe
,显示信息如下:
systemd(1)───docker(1101)───docker-containe(1447)───docker-containe(7088)───entrypoint.sh(7099)───java(7152)─┬─{java}(7177)
- 确定进程中的线程CPU使用情况
注意:同一进程/线程在宿主机的pid和在容器中的pid不一样,其中的对应关系可以通过cat /proc/<pid>/status | grep NSpid
获取
-
宿主机:
通过
top -H -p <pid>
或者ps -To pcpu,tid,pid,user <pid> |sort -r -k1 |more
-
容器:
若使用镜像类似BusyBox,容器内
top -H
不支持,但仍可使用以上宿主机方式获取占用cpu高的线程,只是获取的线程pid为宿主机上pid而非容器内pid若容器内支持
top -H
,则通过以上命令在容器内获取占用cpu高的线程pid
- jvm线程dump
-
宿主机:
通过
jstack
命令,使用jstack -l <pid>
将结果输出到控制台,如果想将内容保存到文件中请使用jstack -l <pid> > jstack_$(date "+%Y%m%d%H%M%S").txt
,其中<pid>
为进程ID。若无jstack
命令,可以考虑通过kill
命令,使用kill -3 <pid>
将结果输出到默认的日志文件中。 -
容器:
进入容器,如上操作。或者无
jstack
命令时,使用jattach,如下。
之后根据线程堆栈中nid
、占用cpu高的线程pid进行进制转换(printf "%x\n" <pid>
),以及注意宿主机和容器线程id mapping,就能定位出代码中消耗cpu的位置了。