Docker(K8S)环境下开启JMX远程监控

·

1 min read

Docker(K8S)环境下开启JMX远程监控

问题引入

JMX(即Java Management Extensions),如果你在网上搜索如何配置JMX,你就会看到这样的一堆配置

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

然后你就会发现在docker下,怎么弄都不对。

JMX分析

JMX其实需要注册三个端口,其作用为:

  • 端口1: 接收注册请求,JMX客户端(如jvisualvm)在连接时,需要填写的端口号

  • 端口2: 用于远程连接,可以与端口1使用同一个端口号

  • 端口3: 用于本地连接,随机(这个端口在实际业务场景中,不需要去指定,我暂时没研究如何指定这个端口)

排坑

坑点1 JMX端口仅暴露1个

由于JMX是在远程监控的情况下是需要两个端口的,所以在Docker环境下很可能就会出现因为端口没映射全而导致的失败

解决办法也很简单,就是把端口1和端口2设置为同一个端口即可,这样也可以减少端口映射过多而产生的端口冲突

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

注:8888这个端口是我随便写的,在合法范围内都可以

坑点2 java.rmi.server.hostname配置导致JMX连接失败

坑点1其实在网络上已经有大把大把现成的文章了,而对于坑点2,则在于java.rmi.server.hostname这个配置。我个人认为这个是因为JMX诞生比较早,所以JMX并没有适配容器化,这就导致了第二个坑点。

java.rmi.server.hostname配置失败的体现在于,你的JMX客户端,会在连接中卡顿很久,这其实就是JMX尝试连接,但连接不上导致的。

JMX客户端根据你填写的IP和PORT去查找JMX服务,这时候你的服务端会返回这个java.rmi.server.hostnamecom.sun.management.jmxremote.rmi.port,JMX客户端再根据这两个值去连接。

那么在docker环境下,你配置的java.rmi.server.hostname很可能就配置错了,你需要保证这个java.rmi.server.hostname是客户端直接可连的,并且这个com.sun.management.jmxremote.rmi.port也是可以直接访问的。

我使用的环境是我用我的笔记本去监控运行在服务器K8S集群中的服务,这种情况下,我需要把java.rmi.server.hostname配置为这个集群所使用的映射服务IP,

如果你的映射服务IP过多,这就会很麻烦,因为每次修改java.rmi.server.hostname需要重启,而重启等同于重新部署,这就导致有可能不匹配,这个问题可能需要想办法绑定,或者自己手动用kubectl做映射

并且你还需要保证com.sun.management.jmxremote.rmi.port是映射服务所使用的端口。

创建端口映射的时候,就保证你的容器端口和映射端口得是一致的,不然JMX服务返回给JMX客户端的端口,没办法通过端口映射连接了

在这里插入图片描述

参考

how-to-connect-with-jmx-from-host-to-docker-container-in-docker-machine