【发布时间】:2017-04-25 11:30:06
【问题描述】:
我正在尝试使用 JConsole、Java Mission Control 等客户端连接到我在 Java 应用程序(Java 8 和 Spring Boot 1.4 和 Tomcat)上定义为 1099(默认值)的 JMX 端口,或 Java VisualVM,但我遇到了一个错误:
java.rmi.ConnectException: Connection refused to host: 10.xxx.xxx.xx, nested exception is:
java.net.ConnectException: Connection timed out
...
请注意,我隐藏了确切的主机 IP,但它是部署我的服务的特定 Kubernetes 管理的 Docker 容器的 pod IP。我尝试使用以下服务 URL 连接到 JMX 端口:
jconsole service:jmx:rmi://<nodeIP>:<nodePort>/jndi/rmi://<nodeIP>:<nodePort>/jmxrmi
我知道 JMX 打开了一个 random high port,我试图通过包含一个 custom @Configuration class that forces that high port to also serve on port 1099 来解决这个问题。我已经进入实际的容器和 pod 并运行了
netstat -tulpn
查看打开的端口,我确认打开的唯一端口是 8443(我的应用程序正在运行)和 1099(JMX 端口);这表明我的课有效。我还确保 Kubernetes 端的 1099 端口是开放的,所以这不是阻塞它的原因。
正如许多关于 JMX 远程连接的答案所暗示的那样,我尝试了以下 Java 选项的多种变体,但均无济于事:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.jmi.port=1099 -Djava.rmi.server.hostname=0.0.0.0
答案建议强制 JMX 端口和 RMI 注册表端口相同,但这些都不起作用。
我认为问题可能是因为主机名(我试图使用 -Djava.rmi.server.hostname=0.0.0.0 进行动态化)无法解析每次我创建的不同主机名(pod IP)服务已部署。
因此,连接似乎无法完成,因为 JMX 在部署我的服务后无法查看 Kubernetes 分配的主机名。
JMX 有没有办法识别 Kubernetes 主机名?或者,是否有其他方法可以通过 Kubernetes 部署的服务远程连接到 JMX 端口?
编辑 1: 我做了一些额外的研究,也许一个可选的 JMXMP 代替 RMI 可以工作?有没有人用 Tomcat 完成这个工作?
【问题讨论】:
-
你试过用
kubectl port-forward [podname] 1099:1099来测试它是否在听吗? -
另外,10.xxx.xxx.xxx range of IPs are reserved。这不是公共 IP,因此您可能无法连接到它。您可能需要设置服务和入口以通过节点的 IP 地址与您的 pod 对话。
-
@3ocene 端口转发在我们的例子中不是一个选项。我们需要能够针对我们的情况使用节点端口。 10.xxx.xxx.xxx 地址是私有 IP,集群是我们私有网络的一部分。请注意,我们从集群中的一个节点到 podIP:1099 进行了 ssh 隧道,并且连接正常,但它不适用于 node:nodePort。
-
需要明确的是,@realgenob 也在与我合作并遇到同样的问题。
-
您是否尝试过指定-Djava.rmi.server.hostname=10.x.x.x?我们对 Openstack 虚拟机进行了类似的设置,其中 OpenStack 将内部 IP 分配给虚拟机,但您使用外部路由 IP 来访问应用程序。所以我们用外部 IP 指定了那个参数并且它起作用了(当然,当你想要动态地制作它时,你会遇到下一个问题)。
标签: java docker spring-boot kubernetes jmx