2017-08-01 72 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