Linux入门实践笔记(七)——云服务器中配置Java项目的JMX连接失败问题解决记录
内容
笔者在阿里云服务器中配置Java项目的JMX远程连接,在确认JVM参数、防火墙、阿里云安全组设置都无误后,使用JConsole等工具连接JVM时仍出现JMX连接失败的问题。笔者将该问题的解决方法记录成文,供网友遇到同样问题时能快速的处理。
版本
操作系统: CentOS 7.2 64位
JDK:1.8.0_181
说明
转载请说明出处:Linux入门实践笔记(七)——云服务器中配置Java项目的JMX连接失败问题解决记录
JMX连接的官方文档:https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html
为何要开启JMX监控
作为一名Java开发人员,大多数情况下,只要确保写好的代码功能能跑通即可,很少关注代码对CPU、内存、线程的资源依赖情况。但是如果出现了Out-Of-Memory等问题,或想监控Java项目的运行状况(比如在进行压力测试时),可以使用JMX客户端监控JVM的资源使用情况。常用的JMX客户端有JConsole、JMC、JVisualVM,这些都是JDK自带的工具。
开启JVM的JMX监控
在启动jar包时添加com.sun.management.jmxremote.* 相关的JVM参数,该示例以7199为JMX远程监控的端口,不使用SSL安全连接,不启用账号密码认证:
[user@ServerA2 jars]$ java -Dcom.sun.management.jmxremote.port=7199 #供JMX客户端远程连接用的端口号
-Dcom.sun.management.jmxremote.authenticate=false #关闭账号密码认证,不安全,仅在开发阶段使用
-Dcom.sun.management.jmxremote.ssl=false #关闭SSL
-Djava.rmi.server.hostname=106.117.142.x #指定本机供远程访问的IP地址,此处是本机的公网IP
-Xms512m -Xmx512m -jar zuul-1.0-SNAPSHOT.jar &
其中-Djava.rmi.server.hostname参数一定要设置,否则连接失败。
云服务器JMX连接失败原因
正确地配置了JVM参数后启动jar包,在本地仍然无法使用JMX Client访问云服务器上的JVM。笔者在阿里云提交了工单,经过长达两天时间多次沟通后终于得知JMX连接失败的原因。
开启JMX远程监控管理功能后,JVM不仅会占用指定的com.sun.management.jmxremote.port配置的端口号7199,还会额外再开启两个随机的端口号用于通信。如果这两个随机的端口号没有开放访问,那么远程JVM Client还是无法连接到JVM的。
执行netstat -nltp
命令可以查看JVM进程监听的端口,本示例中启动的java进程的PID为15703,通过下面的查询可知需要额外放行的两个端口为41264和41665。
[user1@ServerA2 jars]$ netstat -nltp
#其中:-n表示表示输出中不显示主机,端口和用户名,-lb表示只显示监听listening端口,-t表示只显示tcp协议的端口,-p表示显示进程的PID和进程名称。
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:41264 0.0.0.0:* LISTEN 15703/java
tcp 0 0 0.0.0.0:8881 0.0.0.0:* LISTEN 15703/java
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:7001 0.0.0.0:* LISTEN 15074/java
tcp 0 0 0.0.0.0:7101 0.0.0.0:* LISTEN 15074/java
tcp 0 0 0.0.0.0:7199 0.0.0.0:* LISTEN 15703/java
tcp 0 0 127.0.0.1:32000 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:41665 0.0.0.0:* LISTEN 15703/java
tcp6 0 0 :::80 :::* LISTEN -
将这两个端口号在安全组中放行后,远程JMX Client就可以正常访问JVM,真坑。