在docker内定位占用cpu过高的java线程

参考 ​>

  1. 确定进程信息
  • 判断该进程是否在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)
  1. 确定进程中的线程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

  1. 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的位置了。

posted on 2023-07-21 20:13  -赶鸭子上架-  阅读(540)  评论(0编辑  收藏  举报