在GCE上的Docker中将VisualVM或JConsole附加到Java

时间:2017-08-01 22:57:01

标签: java docker google-compute-engine jmx visualvm

我正在尝试在远程Java-in-Docker进程中进行一些CPU采样。

我已经在这里看了相关的问题,并尝试了一切,但没有用,所以我在这里发布我的设置。

我在Google Compute Engine(GCE)实例上的Docker容器中运行了一个Java进程(openjdk-8)。 GCE实例和容器都运行Debian-9。我想将VisualVM或JConsole附加到我的Java进程。

我可以在本地运行我的docker容器,并使用localhost:9010连接visualvm和jconsole。

我在VM启动脚本中使用以下命令启动容器:

docker run -d -p 9010:9010 <my container>

Dockerfile还有:

EXPOSE 9010

由Dockerfile CMD启动的Java进程具有以下相关参数:

"-Dcom.sun.management.jmxremote", \
"-Dcom.sun.management.jmxremote.port=9010", \
"-Dcom.sun.management.jmxremote.rmi.port=9010", \
"-Dcom.sun.management.jmxremote.local.only=false", \
"-Dcom.sun.management.jmxremote.authenticate=false", \
"-Dcom.sun.management.jmxremote.ssl=false", \

我使用以下方法在我的gcloud防火墙中打开了端口9010:

gcloud compute firewall-rules create jmx-port --allow=tcp:9010,udp:9010

我已经使用netcat验证了端口是否已打开,我可以与它建立TCP连接。

我在同一个Docker容器中打开了其他端口,客户端成功连接到这些端口。它们以相同的方式暴露并映射到主机端口(-p port:port),并以相同的方式在防火墙中打开。

我正在传递GCE实例的外部IP地址。例如,如果我这样做:

gcloud compute instances list

它告诉我:

NAME            ZONE           MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP      STATUS
my-server-b23j  us-central1-d  n1-standard-1               10.240.0.2   108.357.213.99   RUNNING

然后我会使用这个论点:

108.357.213.99:9010

作为远程jmx连接主机:端口对。

VisualVM和JConsole都告诉我他们无法连接到远程JMX服务。在这两种情况下,我拒绝安全连接,然后他们说:

Cannot connect to 108.357.213.99:9010 using
service:jmx:rmi:////jndi/rmi://108.357.213.99:9010/jmxrmi

绝望之下,我添加了一个防火墙规则,在所有端口0-65535上启用TCP / UDP连接,但它没有什么区别 - 它们仍然无法连接。

我已经读过JMX-RMI打开匿名端口,并且您可以(至少部分?)通过指定两者来禁用此行为:

"-Dcom.sun.management.jmxremote.port=9010", \
"-Dcom.sun.management.jmxremote.rmi.port=9010", \

但是,在我的情况下,它并没有做到这一点。

我已阅读here您需要指定rmi服务器主机名:

-Djava.rmi.server.hostname='192.168.99.100'

但我的服务器IP是短暂的 - 它是在我创建实例时由Google Compute Engine分配的,因此我无法将其与其他Java args一起硬连接到Dockerfile中。

我是否需要获取静态IP地址才能使其正常工作?

1 个答案:

答案 0 :(得分:3)

一种可能的解决方案是将ssh插入您的GCE盒和端口转发端口9010.这可以通过本地控制台完成:

gcloud compute ssh name-of-your-gce-engine -- -L 9010:localhost:9010

然后在jconsolejvisualvm中,您将连接到localhost:9010。在这里使用localhost意味着jconsole/jvisualvm将连接到您的本地计算机,此连接通过ssh隧道传输到您的GCE引擎以及-L参数中定义的主机和端口,{{1}但是从GCE引擎的角度来看。这意味着你将最终得到你的申请。

您仍然必须在启动程序之前设置rmi服务器名称,但必须使用

localhost:9010

以便RMI告诉-Djava.rmi.server.hostname='localhost' 使用localhost,然后这将解析为本地隧道端点。当然,你仍然需要这些:

jconsole/jvisualvm