知识普及
jmx
JMX(java Management Extensions)是一个Java平台的管理和监控接口。任何程序,只要按JMX规范访问这个接口,就可以获取所有管理与监控信息,jconsole与Java VisualVM等常见监测工具都是基于jmx,JMX不但可以用于管理JVM,还可以管理应用程序自身。
JMX把所有被管理的资源都称为MBean(Managed Bean),MBean全部由MBeanServer管理,如果要访问MBean,可以通过MBeanServer对外提供的访问接口,例如RMI或HTTP。
jconsole
JConsole 是一个内置的 Java 性能分析器,具备相对完善的图形界面。可以轻松地使用 JConsole来监控 Java 应用程序性能和跟踪 Java 代码。
其他监测工具
使用jconsole连接远程应用
准备
- java版本: 1.11/1.8
- 确保jmx监听的端口可通,可以通过telnet命令测试
1:非认证远程连接应用
命令:
java -Dcom.sun.management.jmxremote.port=8079 -Dcom.sun.management.jmxremote.rmi.port=8079 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=${ip} -jar demo-0.0.1-SNAPSHOT.jar
- 1
参数解释:
-Djava.rmi.server.hostname=${ip} #远程服务器ip
-Dcom.sun.management.jmxremote.port=${port} #jmx 端口号
-Dcom.sun.management.jmxremote.rmi.port={port} #rmi连接端口号
-Dcom.sun.management.jmxremote.ssl=false # 关闭ssl
-Dcom.sun.management.jmxremote.authenticate=false #关闭密码身份认证
- 1
- 2
- 3
- 4
- 5
执行远程非认证连接:
所参考oracle文档:
https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html#gdeum
2:使用密码远程连接应用
创建jmx授权用户并赋予权限:
- 进入$JAVA_HOME/conf/management/目录,java8是在 $JAVA_HOME/jre/lib/management目录
- 参照目录下的jmxremote.password.template文件创建jmxremote.password
- 在jmxremote.password新建用户名与密码
- 在本目录的jmxremote.access文件为新增用户设置权限,这里我设置为只读
- 将jmxremote.password文件复制到jar包目录,这一步可省略
- 设置文件权限,命令如下
chmod 600 jmxremote.password
- 1
执行命令启动应用:
java -Dcom.sun.management.jmxremote.port=8079 -Dcom.sun.management.jmxremote.rmi.port= 8079 - Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=${ip} -Dcom.sun.management.jmxremote.password.file=${jmxremote.password} -jar demo-0.0.1-SNAPSHOT.jar
- 1
执行远程密码认证连接:
效果图:
所参考oracle文档:
https://docs.oracle.com/javadb/10.10.1.2/adminguide/radminjmxenablepwd.html
说明:
生产环境jmx远程连接建议使用ssl证书认证方式,此种方式更加安全,这里我给只读用户使用密码认证只是个例子。
3:使用数字证书远程连接应用
说明
- java8此步骤需要用到密码认证方式的用户名与密码,java11不需要。
- 认证原理图:
从图中可以看出我们需要给客户端与服务端都生成密钥对,同时双方的受信密钥库都包含对方的公钥,这样就确保只有公钥在服务端的受信密钥库中的jconsole才被允许连接,这与web https有点不同,不过原理是差不多的。
为jconsole生成ssl证书
- 进入$JAVA_HOME/bin目录,java8是在 $JAVA_HOME/jre/bin目录,
- 执行如下命令生成密钥对:
keytool -genkeypair -alias jconsole -keyalg RSA -validity 365 -storetype pkcs12 -keystore jconsole.keystore -storepass 123456 -keypass 123456 -dname "CN=名称,OU=组织下属单位,O=组织名,L=城市,S=省份,C=CN"
- 1
参数说明:
-alias jconsole 密钥对别名为jconsole
-keystore jconsole.keystore 密钥库名称为jconsole.keystore
-storepass 123456 存储密码为123456
-keypass 123456 密钥密码为123456
-dname 证书申请实体信息
- 1
- 2
- 3
- 4
- 5
- 执行如下命令导出证书:
keytool -exportcert -alias jconsole -storetype pkcs12 -keystore jconsole.keystore -file jconsole.cer -storepass 123456
- 1
- 查看生成结果:
前2步骤顺利的话会在当前文件夹看到以下文件:
- 执行命令将证书导入到应用的truststore(受信的密钥库)中:
keytool -importcert -alias jconsole -file jconsole.cer -keystore jconsole-ssl.truststore -storepass 123456 -noprompt
- 1
参数说明:
-storepass 123456 受信密钥库密码为123456
- 1
执行成后会看到受信密钥库如下:
6. 将受信密钥库上传的应用服务器
7. 生成服务端应用的密钥对
keytool -genkeypair -alias app -keyalg RSA -validity 365 -storetype pkcs12 -keystore app.keystore -storepass 123456 -keypass 123456 -dname "CN=app名称,OU=app组织下属单位,O=app组织名,L=城市,S=省份,C=CN"
- 1
- 导出应用app的证书
keytool -exportcert -alias app -storetype pkcs12 -keystore app.keystore -file app.cer -storepass 123456
- 1
- 将应用的证书导入到jconsole的truststore(受信的密钥库)中:
keytool -importcert -alias app -file app.cer -keystore app-ssl.truststore -storepass 123456 -noprompt
- 1
- 上传应用的密钥对到服务器
- 设置应用启动脚本如下:
java8:
java -Dcom.sun.management.jmxremote.port=8079 -Dcom.sun.management.jmxremote.rmi.port=8079 -Djava.rmi.server.hostname=${ip} -Dcom.sun.management.jmxremote.password.file=${path} -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.ssl=true -Dcom.sun.management.jmxremote.registry.ssl=true -Dcom.sun.management.jmxremote.ssl.need.client.auth=true -Djavax.net.ssl.trustStore=/home/iic/jconsole-ssl.truststore -Djavax.net.ssl.trustStorePassword=123456 -Djavax.net.ssl.keyStore=${path} -Djavax.net.ssl.keyStorePassword=123456 -jar demo-0.0.1-SNAPSHOT.jar
- 1
java11:
java -Dcom.sun.management.jmxremote.port=8079 -Dcom.sun.management.jmxremote.rmi.port=8079 -Djava.rmi.server.hostname=${ip} -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=true -Dcom.sun.management.jmxremote.registry.ssl=true -Dcom.sun.management.jmxremote.ssl.need.client.auth=true -Djavax.net.ssl.trustStore=${path} -Djavax.net.ssl.trustStorePassword=123456 -Djavax.net.ssl.keyStore=${path} -Djavax.net.ssl.keyStorePassword=123456 -jar demo-0.0.1-SNAPSHOT.jar
- 1
参数说明:
-Djavax.net.ssl.trustStore=${path} 受信密钥库路径
-Djavax.net.ssl.trustStorePassword=123456 受信密钥库密码
- 1
- 2
- 使用ssl连接远程服务,在jconsole目录执行以下命令:
jconsole -J-Djavax.net.ssl.trustStore=F:\professional\java-cert\app-ssl.truststore -J-Djavax.net.ssl.trustStorePassword=123456 -J-Djavax.net.ssl.keyStore=F:\professional\java-cert\jconsole.keystore -J-Djavax.net.ssl.keyStorePassword=123456
- 1
用户名和口令java8需要输入,java11直接跳过,密钥对与受信密钥库的密码一定不要搞错。
13. 效果图
参考文档:
https://www.cleantutorials.com/jconsole/jconsole-ssl-with-password-authentication