我的应用程序在docker中运行核心操作系统和Ubuntu。如何从这些系统收集线程转储以分析性能问题?
我已尝试以下命令,但它们没有起作用:
kill -3
jstack
docker exec
appsnap
我有一个在Docker中运行的Java
应用程序,我使用:docker exec -it <containerName> jstack > someFile.txt
。请确保定期收集它以更好地了解。
此外,您可以使用yourkit
等应用程序为您执行此操作。
根据容器的构建方式,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
find
也不可用,您可以使用 cat /proc/<PID>/cmdline
手动搜索 /proc
中的进程目录。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:
[ .... ]
有几个线程转储 shell 脚本可以帮助您在 https://access.redhat.com/solutions/18178 上(在附件下面)。
基本用法:
sh ./threaddump_linux.sh JAVA_PID
您必须将此添加到您的Dockerfile或进入容器并手动安装和运行它。
使用它们的说明(以及其他线程转储技术)在该页面上。
docker exec -it <containerName> kill -3 1
docker logs <containerName>