为什么在容器中 1 号进程挂不上 arthas?

💡 原文中文,约6100字,阅读约需15分钟。
📝

内容提要

在容器环境中,由于 Alpine 自带的 musl 对 confstr(_CS_GNU_LIBPTHREAD_VERSION,) 返回 0,jvm 会认为是 LinuxThread,导致 attach 失败。可以通过 shell 模拟发送信号,或者设置启动参数 -XX:+StartAttachListener,或者修改镜像,来解决这个问题。

🎯

关键要点

  • 在容器环境中,Java 进程为 1 号进程时,无法使用 arthas,出现 AttachNotSupportedException 错误。
  • 问题的原因是 Alpine 自带的 musl 对 confstr(_CS_GNU_LIBPTHREAD_VERSION,) 返回 0,导致 JVM 认为是 LinuxThread。
  • 正常的 attach 流程包括查找 Unix socket 和发送 SIGQUIT 信号,但在 1 号进程时无法找到父进程。
  • LinuxThread 机制通过 fork 和共享内存实现线程,但存在缺陷,NPTL 机制更为标准。
  • 解决方法包括通过 shell 模拟发送信号、设置启动参数 -XX:+StartAttachListener 或修改镜像。
  • 使用 shell 模拟发送信号的方式可以在不重启容器的情况下解决问题。
  • 设置 JVM 启动参数可以自动启动 Attach Listener,但可能需要重启应用。
  • 修改镜像是根本解决方案,OpenJDK 11 已解决此问题,Alpine 的 OpenJDK 8 也已打补丁修复。
  • 了解底层机制有助于技术人员在排查问题和架构设计上有更多自由度。
🏷️

标签

➡️

继续阅读