如何从Docker中获取线程转储(threaddump)

5

我的应用程序在docker中运行核心操作系统和Ubuntu。如何从这些系统收集线程转储以分析性能问题?

我已尝试以下命令,但它们没有起作用:

kill -3
jstack
docker exec
appsnap
4个回答

5

我有一个在Docker中运行的Java应用程序,我使用:docker exec -it <containerName> jstack > someFile.txt。请确保定期收集它以更好地了解。

此外,您可以使用yourkit等应用程序为您执行此操作。


0

根据容器的构建方式,jstack 可能不可用:

$ docker exec -it mycontainer jstack
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "jstack": executable file not found in $PATH: unknown

首先需要在容器中安装JDK包,这似乎有点过度。

对我有效的一种方法是使用QUIT信号方法来获取堆栈转储。这适用于所有容器,而不仅仅是Ubuntu。

要生成堆栈转储,请连接到容器并查找java进程的PID。容器中的PID与容器外部不同。

更新:如果您能找到正确的PID,则可以从主机(容器外部)向进程发送QUIT信号。

您可能会发现容器中未安装pidof和某些情况下甚至未安装ps实用程序。如果所有尝试都失败了,您可以在/proc文件系统中找到PID。

$ docker exec -it mycontainer /bin/sh
sh-4.2$ find /proc -maxdepth 2 -name "cmdline" -exec grep '[j]ava' '{}' \;
Binary file /proc/1709/cmdline matches

我们需要的 PID 是 1709。如果 find 也不可用,您可以使用 cat /proc/<PID>/cmdline 手动搜索 /proc 中的进程目录。
现在向该 PID 发送 QUIT 信号(再次强调,这是在容器中完成的):
sh-4.2$ kill -QUIT 1709

现在你需要弄清楚进程的stdout输出到哪里了。在我的情况下,我很幸运,stdout最终出现在Docker日志中(在主机上):
$ docker logs --since 1m mycontainer
2022-10-19 09:33:01
Full thread dump OpenJDK 64-Bit Server VM (11.0.5+10-LTS mixed mode, sharing):

Threads class SMR info:
[ .... ]

0

有几个线程转储 shell 脚本可以帮助您在 https://access.redhat.com/solutions/18178 上(在附件下面)。

基本用法:

sh ./threaddump_linux.sh JAVA_PID

您必须将此添加到您的Dockerfile或进入容器并手动安装和运行它。

使用它们的说明(以及其他线程转储技术)在该页面上。


0
在我所了解的情况下,容器内的Java进程的PID为1。因此,我可以使用以下命令触发线程转储:
docker exec -it <containerName> kill -3 1

然后用收割输出。
docker logs <containerName>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接