远程JMX连接

107

我正试图打开到运行在远程计算机上的Java应用程序的JMX连接。

该应用程序JVM配置如下:

  • com.sun.management.jmxremote
  • com.sun.management.jmxremote.port=1088
  • com.sun.management.jmxremote.authenticate=false
  • com.sun.management.jmxremote.ssl=false

我可以使用jconsole或jvisualvm使用localhost:1088进行连接。 但是,我无法从远程计算机使用xxx.xxx.xxx.xxx:1088进行连接。

服务器之间没有防火墙,也没有操作系统上的防火墙。但是,为了排除这种可能性,我使用telnet xxx.xxx.xxx.xxx 1088测试,我认为它连接成功了,因为控制台屏幕变空了。

两个服务器都是Windows Server 2008 x64。尝试使用64位和32位JVM,都不起作用。


1
可能与https://dev59.com/hHVC5IYBdhLWcg3w51hv有关。 - tuler
这里有一份详细的指南:https://dev59.com/OHRA5IYBdhLWcg3wxA5N#11654322 - sorin
12个回答

129

如果是在Linux上,问题就在于localhost是回环接口,你需要让应用程序绑定到你的网络接口

你可以使用netstat来确认它未绑定到预期的网络接口。

你可以通过使用系统参数java.rmi.server.hostname="YOUR_IP"来使它工作,可以将其设置为环境变量或使用命令行。

java -Djava.rmi.server.hostname=YOUR_IP YOUR_APP

7
不要忘记使用 hostname -i 命令,详情请参考 https://dev59.com/OHRA5IYBdhLWcg3wxA5N#11654322。 - sorin
成功了!在我们的环境中,我们使用VMWare虚拟机。服务器在一个虚拟机上运行。该虚拟机是围栏部署的,因此它具有内部和外部IP地址。我们使用"-Djava.rmi.server.hostname=<external-ip-address>"启动了服务器Java进程。 - buzz3791
要设置主机IP或更改本地主机IP,可以使用此链接:http://stackoverflow.com/a/23338592/1635051。 - Reza Ameri
我这里有两个问题 - 1)如果想使用JMXMP而不是JMX,那么配置应该怎么做?2)是否可以在不加载RMI协议的情况下建立JMX连接? - Kumar Vaibhav

72

我花了一天以上的时间尝试让JMX在本地主机外部工作。看起来SUN/Oracle没有提供关于这个问题的好文档。

请确保以下命令返回您的真实IP或主机名。如果它返回像127.0.0.1、127.0.1.1或localhost之类的东西,则无法正常工作,您需要更新/etc/hosts文件。

hostname -i

这是启用JMX甚至从外部访问所需的命令

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.port=1100
-Djava.rmi.server.hostname=myserver.example.com

正如您所假设的那样,myserver.example.com 必须与 hostname -i 返回的内容匹配。

显然,您需要确保防火墙不会阻止您,但我几乎可以确定这不是您的问题,问题在于最后一个参数未被记录。


添加 -Djava.rmi.server.hostname=myserver.example.com 就解决了问题!谢谢! - Jim Bethancourt
我已经擅自为此打开了一个JDK文档错误报告:https://bugs.openjdk.java.net/browse/JDK-8066405 - Klara
3
请确保以下命令返回真实的IP地址或主机名。如果它返回类似于127.0.0.1、127.0.1.1或localhost这样的内容,它将无法正常工作,您需要更新/etc/hosts文件。 - PedroD
1
只是一个快速的提示,java.rmi.server.hostname=<AWS EC2控制台中实例的公共DNS名称>。希望这能帮助到某些人。 - Sonny
@PedroD:你需要在 /etc/hosts 中添加一个条目,包含你的公共 IP 和你用于 "-Djava.rmi.server.hostname" 的主机名。 - Sebastian

28

在我对Tomcat和Java 8进行测试时,JVM除了指定的 JMX 端口外还打开了一个临时端口。如果你遇到 JMX 客户端(例如 VisualVM)无法连接的问题,请尝试以下代码来解决它。

-Dcom.sun.management.jmxremote.port=8989
-Dcom.sun.management.jmxremote.rmi.port=8989

还可以参见为什么Java在配置JMX时会开启3个端口?


12

8

看起来您的结束引号出现得太早了。它应该在最后一个参数之后。

这个技巧对我有用。

我注意到一件有趣的事情:当我使用以下命令行启动我的应用程序时:

java -Dcom.sun.management.jmxremote.port=9999
     -Dcom.sun.management.jmxremote.authenticate=false
     -Dcom.sun.management.jmxremote.ssl=false

如果我尝试使用jconsole从远程机器连接到该端口,TCP连接成功,远程jconsole和本地jmx代理之间交换了一些数据,我的MBean部署在其中,然后jconsole显示连接错误消息。我进行了wireshark捕获,它显示来自代理和jconsole的数据交换。
因此,这不是网络问题,如果我执行netstat -an,无论是否使用java.rmi.server.hostname系统属性,都有以下绑定:
 TCP    0.0.0.0:9999           0.0.0.0:0              LISTENING
 TCP    [::]:9999              [::]:0                 LISTENING

这意味着无论何种情况下,端口9999上创建的套接字都可以接受来自任何主机和任何地址的连接。
我认为该系统属性的内容在连接时某处被使用,并与代理用于与jconsole通信的实际IP地址进行比较。如果这些地址不匹配,则连接失败。
当我使用jconsole从同一主机连接时,我没有遇到这个问题,只有在真正的物理远程主机上才会遇到。因此,我认为只有在连接来自“外部”时才进行此检查。

“你的结束引号过早”是什么意思?我遇到了同样的问题,我看到TCP连接已建立,但最终 jconsole 声称连接失败。 - tsuna
我不知道,如果我记得正确的话,有一个引号没有在参数的末尾,可能是在批处理脚本中,但我必须承认这个答案与问题无关...也许问题已经被编辑了?问题下面没有编辑通知...我不知道,很抱歉。 - yohann.martineau

7

对我有效的方法是将/etc/hosts设置为将主机名指向IP地址而不是环回接口,然后重新启动我的应用程序。

cat /etc/hosts

127.0.0.1      localhost.localdomain localhost
192.168.0.1    myservername

这是我的配置:
-Dcom.sun.management.jmxremote.port=1617 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false

是的,这对我也有效。那么 hostname 究竟是做什么的呢? - puppylpg

5

非常感谢,它的工作原理如下:

java -Djava.rmi.server.hostname=xxx.xxx.xxx.xxx -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=25000 -jar myjar.jar


2

我知道这个帖子很旧了,但有一个额外的选项可以大大提高效率。请看这里:https://realjenius.com/2012/11/21/java7-jmx-tunneling-freedom/

-Dcom.sun.management.jmxremote.rmi.port=1099

这段文字是关于IT技术的内容,介绍了一种能够提高效率的选项。如果你需要更多信息,请点击链接查看详细介绍。同时,代码块中的内容也是需要注意的配置项。

1

为了启用JMX远程,需要在JAVA命令中传递以下VM参数。

    -Dcom.sun.management.jmxremote 
    -Dcom.sun.management.jmxremote.port=453
    -Dcom.sun.management.jmxremote.authenticate=false                               
    -Dcom.sun.management.jmxremote.ssl=false 
    -Djava.rmi.server.hostname=myDomain.in

1
你能告诉我为什么它绑定到0.0.0.0而不是特定的IP吗? - Babu James
0.0.0.0是特殊的,意思是“所有IP”。 - Gabriel

1

尝试这个,我测试过在Docker容器中访问JMX

-Dcom.sun.management.jmxremote=true -Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.port=16000 -Dcom.sun.management.jmxremote.rmi.port=16000 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

然后执行

$ jconsole localhost:16000


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接