是否可以在本地主机和远程 IP 上配置 JMXRemote?

是否可以在本地主机和远程 IP 上配置 JMXRemote?

我有一个在 Kubernetes 中运行的 Java 应用程序。有时我需要调试它,所以我过去常常通过 连接到 jmx 端口kubectl port-forward pods/my-java-app 9010:9010 -n my-java-app

我们的监控团队要求能够远程查询 jmx 端口,因此我相应地重新配置了我的 docker-entrypoint.sh:

    #!/bin/bash
    set -ex
    
    echo "Start docker-entrypoint.sh"
    
    JMXARGS="-Dsun.management.jmxremote.level=FINEST \
          -Dsun.management.jmxremote.handlers=java.util.logging.ConsoleHandler \
          -Djava.util.logging.ConsoleHandler.level=FINEST \
          -Dcom.sun.management.jmxremote.local.only=false \
          -Dcom.sun.management.jmxremote.ssl=false \
          -Dcom.sun.management.jmxremote.authenticate=false \
          -Dcom.sun.management.jmxremote.port=$JMX_PORT \
          -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT \
          -Djava.net.preferIPv4Stack=true" 
    
    /usr/local/openjdk-8/bin/java ${JAVA_OPTS} ${JMXARGS} \
        -XX:+HeapDumpOnOutOfMemoryError \
        -XX:+UseContainerSupport \
        -XX:+UseG1GC -DLOG_PATH=${LOG_PATH}  \
        -DAPP_LOG_FILENAME=${APP_LOG_FILENAME} \
        -jar /opt/${JARFILENAME} \
        -conf /opt/${CONFFILENAME} \
        -server -XX:CompileThreshold=5 \
        -Djava.net.preferIPv4Stack=true \
        -XX:-OmitStackTraceInFastThrow \
        -Dserver.port="${LISTENING_PORT}" \
        run myjavaapp

从那时起,我无法使用 kubectl port-foward 从我的计算机查询 jmx。监控团队的监控服务器与 Kubernetes 集群位于同一本地网络上,因此它可以为他们工作,远程查询 JMX。

我怎样才能两全其美?含义:

  • 拥有远程端口以满足监控团队的需求
  • 通过命令获取端口kubectl port-forward pods/my-java-app 9010:9010 -n my-java-app以便进行调试

编辑:

更进一步来说,这里有一些从容器中运行的测试:

root@my-java-app-864d5d487f-99qwl:/usr/local/openjdk-8# java -cp /jmxquery.jar org.nagios.JMXQuery -U service:jmx:rmi://172.29.4.202/jndi/rmi://172.29.4.202:9010/jmxrmi -O java.lang:type=Memory -A HeapMemoryUsage -K used -I HeapMemoryUsage -J used -w 800000000 -c 900000000
JMX OK 53811560
root@my-java-app-864d5d487f-99qwl:/usr/local/openjdk-8# java -cp /jmxquery.jar org.nagios.JMXQuery -U service:jmx:rmi://127.0.0.1/jndi/rmi://127.0.0.1:9010/jmxrmi -O java.lang:type=Memory -A HeapMemoryUsage -K used -I HeapMemoryUsage -J used -w 800000000 -c 900000000
JMX OK 55908712

从我的电脑上,在端口转发之后:

PS C:\dev> kubectl port-forward pods/my-java-app-864d5d487f-99qwl 9010:9010 -n my-java-app
Forwarding from 127.0.0.1:9010 -> 9010
Forwarding from [::1]:9010 -> 9010
Handling connection for 9010
Handling connection for 9010

...

(in another term:)
PS C:\dev> java -cp jmxquery.jar org.nagios.JMXQuery -U service:jmx:rmi://127.0.0.1/jndi/rmi://127.0.0.1:9010/jmxrmi -O java.lang:type=Memory -A HeapMemoryUsage -K used -I HeapMemoryUsage -J used -w 800000000 -c 900000000                                                     
JMX CRITICAL Connection timed out: connect

此致,

答案1

您的第二个连接超时了;它并没有被拒绝。因此,我得出结论,JMX RMI 接口(顺便说一句,真讨厌)是单线程的并且阻塞;可能 JMX 客户端在轮询之间保持连接。

JMX RMI 也确实非常慢,这取决于您是否想要抓取大量数据以及您的客户端正在使用哪种 API(jconsole 的缓慢而稳定的方法)或快速而高效的机制,当您遇到缺少序列化接口的 mbean 时,它将因序列化异常而爆发。

一种可能更好的方法(尽管这可能需要更改您的监控)是使用基于 JMX 代理的机制。这是大多数监控提供商(例如 Data Dog、Prometheus)用来收集数据的机制。也可能是一个更好的安全边界。

我只使用过 Prometheus 的 jmx_exporter,但它可能不适合 Nagios。我完全相信会有其他 JMX 代理不会有 JMX RMI 的限制……特别是我认为鬼椒属因通过 HTTP 公开 JMX 而广受欢迎

另一种可能性:如果使用 jconsole(它可以使用 Attach API 将自身注入为代理(?),这就是为什么您不需要设置 JMX RMI 来使用 jconsole)您可能会发现这可以解决 JMX RMI 端口的争用问题。

相关内容