使用VisualVM和JMX进行远程监控

29

我想使用jvisualvm(或jconsole)监控远程运行的Java(Spring Boot)应用程序。 当本地运行时,我可以在jvisualvm和jconsole中看到托管的bean。 在远程运行时,我无法连接。 我尝试了几个不同的Java进程(例如spring xd)。 在SO和Google上寻找答案没有帮助。

这是我在远程主机上的JAVA_OPTS:

$ echo $JAVA_OPTS
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.59.99

然后我只需要按照以下方式启动程序(这是为spring xd准备的,但我在其他Java程序中遇到了同样的问题)。

$ bin/xd/xd-singlenode
服务器进程似乎会获取这些选项:
$ ps -ef | grep single
vagrant  22938 19917 99 06:38 pts/2    00:00:03 /usr/lib/jvm/java-8- oracle/jre/bin/java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.59.99 -Dspring.application.name=admin -Dlogging.config=file:/home/vagrant/spring-xd-1.1.0.RELEASE/xd/config///xd-singlenode-logger.properties -Dxd.home=/home/vagrant/spring-xd-1.1.0.RELEASE/xd -Dspring.config.location=file:/home/vagrant/spring-xd-1.1.0.RELEASE/xd/config// -Dxd.config.home=file:/home/vagrant/spring-xd-1.1.0.RELEASE/xd/config// -Dspring.config.name=servers,application -Dxd.module.config.location=file:/home/vagrant/spring-xd-1.1.0.RELEASE/xd/config//modules/ -Dxd.module.config.name=modules -classpath (...)

远程主机(Ubuntu Linux虚拟机)上的Java版本为:

$ java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

本地机器(Mac OS)上的Java版本略有不同:

$ java -version    
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

在jvisualvm中,我按以下方式添加了远程连接(尝试过使用ssl连接和不使用):

enter image description here

jvisualvm给我的错误消息如下:

Error Message given by jvisualvm

当远程进程正在运行时,我可以使用命令telnet 192.168.59.99:9010从本地主机连接到远程主机,因此这似乎不是防火墙问题。

非常感谢您的任何帮助。


2
请尝试使用以下Java选项:-"Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.59.99",并在Jconsole中使用service:jmx:rmi:///jndi/rmi://192.168.59.99:9010/jmxrmi。 - Arnab Biswas
你救了我的一天。这个可行。你能把它发布为一个答案吗?我会很乐意接受的。 - user152468
很高兴听到它起作用了!已发布为答案。 - Arnab Biswas
3个回答

44
请使用以下JVM选项:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.59.99

在Jconsole中使用以下内容进行连接:

service:jmx:rmi:///jndi/rmi://192.168.59.99:9010/jmxrmi

1
这样在没有身份验证的情况下让它可访问似乎不是一个好主意? - Jack Zach Tibbles
10
@JackZachTibbles 这很常见,尤其在企业防火墙内。 - Kyrstellaine
顺便说一下,通过-D选项提供凭据使得只要用户可以访问运行进程选项(例如Linux上的ps命令),就可以清晰地读取它,这通常在您能够通过ssh连接到服务器时就可以实现...所以...不确定它是否会为安全带来很多保障。 - Frédéric Camblor
好的,那么选项或连接方面有什么不同呢?请展示一下添加/删除了什么,否则很难为其他人修复此问题。 - Krzysztof Krasoń
对我没用,因为这个答案没有提到连接需要第二个(默认动态分配)端口才能工作。在我看来,应该接受thangdc94的回答。 - Tobias Gierke

28

Arnab Biswas的答案在我的情况下不起作用。经过一个小时的研究,我发现JMX运行在RMI之上,因此有2个端口用于JMX:

  • JMX连接端口。 (-Dcom.sun.management.jmxremote.port)
  • (臭名昭著的)漫游RMI数据端口。 (-Dcom.sun.management.jmxremote.rmi.port)

RMI数据端口将打开一个从1099开始的随机端口。通过将RMI注册表和RMI服务器使用的端口设置为相同的端口,隧道将变得更加容易。

所以我需要将-Dcom.sun.management.jmxremote.rmi.port=9010添加到JVM选项中

并且我需要使用以下JVM选项:

-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.rmi.port=9010 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=192.168.59.99

阅读更多:


2
非常感谢!!!我一直在尝试连接一个被防火墙保护的主机,慢慢地变得有些疯狂... 在我看来,这应该是被接受的答案。似乎几乎没有人尝试连接一个位于防火墙后面的机器,所以他们都建议设置“com.sun.management.jmxremote.port”,但没有人提到“com.sun.management.jmxremote.rmi.port”... - Tobias Gierke
1
Ubuntu在防火墙后面,使用UFW jmx和visualvm进行配置。添加此注释以便在Google搜索中显示 :d - Aadam
除了需要声明rmi端口外,在我的Docker机器上,我注意到如果我尝试转发与这些JMX设置中声明的端口不同的端口,则无法正常工作。例如,JMX=8080和Docker端口设置为映射8081:8080将无法访问JMX。如果端口映射为8080:8080,则可以正常工作。浪费了很多令人沮丧的时间! - jocull

1
让我详细地讨论一下。我刚刚连接到了远程服务器。您需要进入存放jar文件的文件夹。假设您想要监视X.jar文件,并且它位于usr/local/文件夹中。因此,首先cd进入该文件夹。然后确保正在运行哪个jdk。您可以通过在Linux中执行which java命令来找到它。在远程服务器的命令行中(通常我们使用PuTTy cmd,我使用MobaXterm),在puTTy 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 -Djava.rmi.server.hostname=192.168.10.0 -jar X.jar

现在让我详细解释一下。这里需要定义rmi端口,因为jmx使用rmi。如果我们不定义rmi端口,它将自动分配一个随机端口。然后我们的连接将无法成功。我们不会使用身份验证和ssl,因为这会导致困难。如果您想尝试,请自行进行。在主机名中,您必须指定远程主机名,即IP地址。 现在在本地计算机上使用位于此文件夹中的visualvm。一般情况下,可以在这个文件夹中找到:

C://Program Files/Java/jdk1.8.0_201/bin 

如果没有安装VisualVM,请下载并将其粘贴到目录中。从本地电脑运行VisualVM。您将看到一些选项,如本地、远程等。在“远程”选项中选择“添加远程主机”。添加您的主机名。在我的情况下,它是192.168.10.0。然后右键单击鼠标并选择“添加jmx连接”。一个窗口将打开并插入您的端口号。在我的情况下,它是9010。您可以指定任何端口号。选择“不需要ssl连接”,不要选择安全凭据。因为我们已经在属性中添加了认证为false。现在连接,您的连接将顺利进行。还有一个建议。您可以使用“jstatd连接”进行连接。但它不起作用。不显示任何输出。可能是因为Java 8问题之类的原因。要监视内存详细信息,您需要更新版本的“visualvm.exe”。您可以下载它。 您可以使用身份验证和SSL进行连接。使用Authentication=true的详细步骤在此链接中讨论:Connect to remote JMX Agent with authentication

本链接讨论了使用 authentication=true 和 SSL=true 的详细步骤:JConsole SSL/TLS with Password Authentication


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