2017-08-01 70 views
0

我试图在远程Java-in-Docker进程中获取一些CPU采样工作。将VisualVM或JConsole附加到GCE上的Docker中的Java

我已经看过这里的相关问题,并尝试了一切,无济于事,所以我在这里发布我的设置。

我有一个在谷歌计算引擎(GCE)实例的Docker容器中运行的Java进程(openjdk-8)。 GCE实例和容器都运行Debian-9。我想将VisualVM或JConsole附加到我的Java进程。

我能够在本地运行我的码头集装箱,并使用localhost:9010与visualvm和jconsole连接。

我开始容器的虚拟机启动脚本:

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

的Dockerfile还具有:

EXPOSE 9010 

Java进程,由Dockerfile CMD开始,具有以下相关ARGS:

"-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 

在绝望中,我添加了一个防火墙规则,允许在所有端口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是短暂的 - 它是由谷歌Compute Engine的,当我创建实例分配的,所以我不能用Java参数的其余部分将它硬连接到Dockerfile中。

我必须得到一个静态IP地址才能使这项工作?

+0

一般来说visualvm在同一主机上效果最好。你可以在云实例中执行它吗? –

回答

2

一个可能的解决办法是ssh到您的GCE箱和端口转发端口9010。这可以从本地控制台来完成与:

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

然后在jconsolejvisualvm您连接到localhost:9010。在这里使用本地主机意味着jconsole/jvisualvm将连接到本地计算机,此连接通过ssh隧道到您的GCE引擎,并在那里与-L参数(localhost:9010)中定义的主机和端口相关,但是从GCE引擎的角度来看。这意味着你将最终在你的应用程序。

你还有启动程序前设置RMI服务器名称,但必须使用

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

使RMI会告诉jconsole/jvisualvm以使用localhost,然后这将解决您的本地隧道的端点。当然,你仍然需要这些:

"-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", \ 
+0

谢谢 - 我会尽快尝试,并让你知道它是否有效。 – user3562927